poj 1679 The Unique MST(次小生成树)
题意:判断最小生成树是否唯一。
分析:只需要判断最小生成树与次小生成树的总权值是否相等。
判断次小生成树的方法:
kruskal O(n^3):先求一次最小生成树,然后枚举去掉生成树中的边,再求n-1次最小生成树,去最小的一棵。
prim O(n^2):先求一次最小生成树,记录树上的边,并且保存每个环中的最大边,然后用一次DP枚举掉树上的边,更新生成树的权和,取最小值。
kruskal
1 /* 2 Author:Zhaofa Fang 3 Lang:C++ 4 */ 5 #include <cstdio> 6 #include <cstdlib> 7 #include <sstream> 8 #include <iostream> 9 #include <cmath> 10 #include <cstring> 11 #include <algorithm> 12 #include <string> 13 #include <utility> 14 #include <vector> 15 #include <queue> 16 #include <stack> 17 #include <map> 18 #include <set> 19 using namespace std; 20 21 typedef long long ll; 22 #define DEBUG(x) cout<< #x << ':' << x << endl 23 #define REP(i,n) for(int i=0;i < (n);i++) 24 #define FOR(i,s,t) for(int i = (s);i <= (t);i++) 25 #define FORD(i,s,t) for(int i = (s);i >= (t);i--) 26 #define PII pair<int,int> 27 #define PB push_back 28 #define MP make_pair 29 #define ft first 30 #define sd second 31 #define lowbit(x) (x&(-x)) 32 #define INF (1<<30) 33 34 35 const int maxn = 5050; 36 int pa[111],a[111]; 37 struct Edge 38 { 39 int u,v,w; 40 }edge[maxn]; 41 42 bool cmp(Edge x,Edge y) 43 { 44 return x.w < y.w; 45 } 46 void init(int n) 47 { 48 FOR(i,1,n)pa[i] = i; 49 } 50 int findset(int x) 51 { 52 return x == pa[x] ? x : pa[x] = findset(pa[x]); 53 } 54 int kruskal(int n,int m,int key) 55 { 56 init(n); 57 int ans = 0,cnt=0; 58 REP(i,m) 59 { 60 if(i == key)continue; 61 int x = findset(edge[i].u),y=findset(edge[i].v); 62 if(x != y) 63 { 64 pa[x] = y;ans += edge[i].w;cnt++; 65 } 66 if(cnt == n-1)return ans; 67 } 68 return -INF; 69 } 70 int main() 71 { 72 //freopen("in","r",stdin); 73 int T; 74 scanf("%d",&T); 75 while(T--) 76 { 77 int n,m; 78 scanf("%d%d",&n,&m); 79 REP(i,m)scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); 80 sort(edge,edge+m,cmp); 81 int ans = 0,cnt=0; 82 init(n); 83 REP(i,m)//最小生成树 84 { 85 int x = findset(edge[i].u),y=findset(edge[i].v); 86 if(x != y) 87 { 88 pa[x] = y;ans += edge[i].w;a[cnt++]=i; 89 } 90 if(cnt == n-1)break; 91 } 92 REP(i,n-1) 93 { 94 int tmp = kruskal(n,m,a[i]); 95 if(ans == tmp) 96 { 97 ans = -INF;break; 98 } 99 } 100 if(ans == -INF)puts("Not Unique!"); 101 else printf("%d\n",ans); 102 } 103 return 0; 104 }
prim
1 /* 2 Author:Zhaofa Fang 3 Lang:C++ 4 */ 5 #include <cstdio> 6 #include <cstdlib> 7 #include <sstream> 8 #include <iostream> 9 #include <cmath> 10 #include <cstring> 11 #include <algorithm> 12 #include <string> 13 #include <utility> 14 #include <vector> 15 #include <queue> 16 #include <stack> 17 #include <map> 18 #include <set> 19 using namespace std; 20 21 typedef long long ll; 22 #define DEBUG(x) cout<< #x << ':' << x << endl 23 #define REP(i,n) for(int i=0;i < (n);i++) 24 #define FOR(i,s,t) for(int i = (s);i <= (t);i++) 25 #define FORD(i,s,t) for(int i = (s);i >= (t);i--) 26 #define PII pair<int,int> 27 #define PB push_back 28 #define MP make_pair 29 #define ft first 30 #define sd second 31 #define lowbit(x) (x&(-x)) 32 #define INF (1<<30) 33 34 35 const int maxn = 5050; 36 int maz[maxn][maxn],path[maxn][maxn]; 37 bool vist[maxn]; 38 int dist[maxn],pre[maxn],Stack[maxn]; 39 int n,m; 40 void init(void){ 41 FOR(i,1,n)FOR(j,1,n)maz[i][j] = INF, path[i][j] = 0; 42 } 43 int prim(int s){ 44 FOR(i,1,n)dist[i] = maz[s][i],vist[i] = 0,pre[i] = s; 45 int top = 0,sum = 0; 46 vist[s] = 1,dist[s] = 0, Stack[top++] = s; 47 while(1){ 48 int u = -1; 49 FOR(i,1,n) 50 if(!vist[i] && (u == - 1 || dist[u] > dist[i])) 51 u = i; 52 if(u == -1)break; 53 sum += dist[u],Stack[top++] = u,vist[u] = 1; 54 REP(i,top){ 55 if(Stack[i] == u)continue; 56 path[Stack[i]][u] = max(path[pre[u]][u],dist[u]); 57 path[u][Stack[i]] = path[Stack[i]][u]; 58 } 59 FOR(i,1,n) 60 if(!vist[i] && (maz[u][i]<dist[i])) 61 dist[i] = maz[u][i],pre[i] = u; 62 } 63 return sum; 64 } 65 void SMT(void){ 66 int Min = INF,sum = prim(1); 67 FOR(i,1,n-1) 68 FOR(j,i+1,n) 69 if(pre[i] != j && pre[j] != i && maz[i][j] < INF) 70 Min = min(Min, sum - path[i][j] + maz[i][j]); 71 if(Min == sum)puts("Not Unique!"); 72 else printf("%d\n",sum); 73 } 74 int main(){ 75 //freopen("in","r",stdin); 76 int T; 77 scanf("%d",&T); 78 while(T--){ 79 scanf("%d%d",&n,&m); 80 init(); 81 int u,v,w; 82 while(m--) 83 { 84 scanf("%d%d%d",&u,&v,&w); 85 maz[u][v] = maz[v][u] = w; 86 } 87 SMT(); 88 } 89 return 0; 90 }
by Farmer