POJ 1679 The Unique MST:次小生成树倍增

Posted Leohh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1679 The Unique MST:次小生成树倍增相关的知识,希望对你有一定的参考价值。

题目链接:http://poj.org/problem?id=1679

题意:

  给你一个图,问你这个图的最小生成树是否唯一。

 

题解:

  求这个图的最小生成树和次小生成树。如果相等,则说明不唯一。

  次小生成树(倍增算法):

    maxn[k][i]:表示从节点i向上走2^k步,这一段中边权的最大值。

    枚举每一条不在MST中的边,求出这条边两端点之间在MST上路径上的最大边权mx。

    次小生成树(非严格) = max(MST - mx + len)

 

AC Code:

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <algorithm>
  5 #include <vector>
  6 #define MAX_N 105
  7 #define MAX_E 10005
  8 #define MAX_K 20
  9 #define INF 1000000000
 10 
 11 using namespace std;
 12 
 13 struct E
 14 {
 15     int s;
 16     int t;
 17     int len;
 18     E(int _s,int _t,int _len)
 19     {
 20         s=_s;
 21         t=_t;
 22         len=_len;
 23     }
 24     E(){}
 25     friend bool operator < (const E &a,const E &b)
 26     {
 27         return a.len<b.len;
 28     }
 29 };
 30 
 31 struct Edge
 32 {
 33     int dest;
 34     int len;
 35     Edge(int _dest,int _len)
 36     {
 37         dest=_dest;
 38         len=_len;
 39     }
 40     Edge(){}
 41 };
 42 
 43 int n,m,t;
 44 int fa[MAX_N];
 45 int dep[MAX_N];
 46 int par[MAX_K][MAX_N];
 47 int maxn[MAX_K][MAX_N];
 48 bool vis[MAX_E];
 49 vector<E> e;
 50 vector<Edge> edge[MAX_N];
 51 
 52 void read()
 53 {
 54     cin>>n>>m;
 55     e.clear();
 56     for(int i=1;i<=n;i++)
 57     {
 58         edge[i].clear();
 59     }
 60     int a,b,v;
 61     for(int i=1;i<=m;i++)
 62     {
 63         cin>>a>>b>>v;
 64         e.push_back(E(a,b,v));
 65     }
 66 }
 67 
 68 void init_union_find()
 69 {
 70     for(int i=1;i<=n;i++)
 71     {
 72         fa[i]=i;
 73     }
 74 }
 75 
 76 int find(int x)
 77 {
 78     return fa[x]==x ? x : fa[x]=find(fa[x]);
 79 }
 80 
 81 void unite(int x,int y)
 82 {
 83     int px=find(x);
 84     int py=find(y);
 85     if(px==py) return;
 86     fa[px]=py;
 87 }
 88 
 89 bool same(int x,int y)
 90 {
 91     return find(x)==find(y);
 92 }
 93 
 94 int kruskal()
 95 {
 96     init_union_find();
 97     sort(e.begin(),e.end());
 98     memset(vis,false,sizeof(vis));
 99     int cnt=0;
100     int res=0;
101     for(int i=0;i<e.size() && cnt<n-1;i++)
102     {
103         E temp=e[i];
104         if(!same(temp.s,temp.t))
105         {
106             cnt++;
107             res+=temp.len;
108             vis[i]=true;
109             unite(temp.s,temp.t);
110             edge[temp.s].push_back(Edge(temp.t,temp.len));
111             edge[temp.t].push_back(Edge(temp.s,temp.len));
112         }
113     }
114     return cnt==n-1 ? res : -1;
115 }
116 
117 void dfs(int now,int p,int d,int l)
118 {
119     dep[now]=d;
120     par[0][now]=p;
121     maxn[0][now]=l;
122     for(int i=0;i<edge[now].size();i++)
123     {
124         Edge temp=edge[now][i];
125         if(temp.dest!=p) dfs(temp.dest,now,d+1,temp.len);
126     }
127 }
128 
129 void init_lca()
130 {
131     dfs(1,-1,0,-1);
132     for(int k=0;k+1<MAX_K;k++)
133     {
134         for(int i=1;i<=n;i++)
135         {
136             if(par[k][i]==-1)
137             {
138                 par[k+1][i]=-1;
139                 maxn[k+1][i]=-1;
140             }
141             else
142             {
143                 par[k+1][i]=par[k][par[k][i]];
144                 maxn[k+1][i]=max(maxn[k][i],maxn[k][par[k][i]]);
145             }
146         }
147     }
148 }
149 
150 int cal_max(int a,int b)
151 {
152     if(dep[a]>dep[b]) swap(a,b);
153     int res=-1;
154     for(int k=0;k<=MAX_K && dep[a]!=dep[b];k++)
155     {
156         if(((dep[b]-dep[a])>>k)&1)
157         {
158             res=max(res,maxn[k][b]);
159             b=par[k][b];
160         }
161     }
162     if(a==b) return res;
163     for(int k=MAX_K-1;k>=0;k--)
164     {
165         if(par[k][a]!=par[k][b])
166         {
167             res=max(res,maxn[k][a]);
168             res=max(res,maxn[k][b]);
169             a=par[k][a];
170             b=par[k][b];
171         }
172     }
173     return max(res,maxn[0][a]);
174 }
175 
176 int sst(int mst)
177 {
178     if(mst==-1) return -1;
179     init_lca();
180     int ans=INF;
181     for(int i=0;i<e.size();i++)
182     {
183         if(!vis[i])
184         {
185             E temp=e[i];
186             int mx=cal_max(temp.s,temp.t);
187             ans=min(ans,mst-mx+temp.len);
188         }
189     }
190     return ans==INF ? -1 : ans;
191 }
192 
193 void work()
194 {
195     int mst=kruskal();
196     if(mst==sst(mst)) cout<<"Not Unique!"<<endl;
197     else cout<<mst<<endl;
198 }
199 
200 int main()
201 {
202     cin>>t;
203     while(t--)
204     {
205         read();
206         work();
207     }
208 }

 

以上是关于POJ 1679 The Unique MST:次小生成树倍增的主要内容,如果未能解决你的问题,请参考以下文章

POJ1679 The Unique MST[次小生成树]

POJ 1679 The Unique MST(次小生成树)

POJ 1679 The Unique MST (次小生成树)

POJ 1679 The Unique MST:次小生成树倍增

poj 1679 The Unique MST (次小生成树(sec_mst)kruskal)

The Unique MST POJ - 1679 次小生成树