POJ 1679 The Unique MST(次小生成树)
2012-10-03 15:35
507 查看
题目链接
题意:最小生成树是否唯一。
数据比较水,用最朴实的方法过的,O(n^2+e)再学一学,这个朴实方法改了N处,,思路简单,Kruskal写的,就是删除生成树里的每一条边,求最小生成树,唉,这是写的啥啊。。。。
O(n^2+e)做法就是看了一下有的kruskal先求出整个生成树,然后先用BFS预处理出生成树上,每一个点和另外的点之间最大的长度,Max[x][y],然后枚举不在生成树的边,min(ans-Max[x][y]+w(x,y))就是次小生成树了。感觉用kruskal比较麻烦,用prim写就比较方便了,可以一边处理,一边更新Max[x][y]。下边代码用prim写的,其主要的思想就是存起他的父亲节点,用生成树里的点到父亲的最大距离,与父亲到自己的距离比较,取大。
题意:最小生成树是否唯一。
数据比较水,用最朴实的方法过的,O(n^2+e)再学一学,这个朴实方法改了N处,,思路简单,Kruskal写的,就是删除生成树里的每一条边,求最小生成树,唉,这是写的啥啊。。。。
#include <cstdio> #include <cstring> #include <map> #include <cmath> #include <algorithm> using namespace std; int o[101],num,sum,m,n; struct edge { int sv; int ev; int w; int flag; } p[200001]; int cmp(const edge &a,const edge &b) { if(a.w < b.w) return 1; else return 0; } int find(int x) { while(x != o[x]) x = o[x]; return x; } void merge(int id,int x,int y,int w,int z) { x = find(x); y = find(y); if(x != y) { sum += w; o[x] = y; if(z == -1)//第一次寻找最小生成树的时候记录下来 p[id].flag = 1; num ++; } } int kruskal(int x) { int i; num = 0; sum = 0; for(i = 1; i <= n; i ++) o[i] = i; for(i = 1; i <= m; i ++) { if(i == x) continue;//删去边x的时候寻找最小生成树 if(num == n-1) break; merge(i,p[i].sv,p[i].ev,p[i].w,x); } if(num == n-1)//特判是否存在最小生成树 return sum; else return -1; } int main() { int i,ans,t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i = 1; i <= m; i ++) { scanf("%d%d%d",&p[i].sv,&p[i].ev,&p[i].w); p[i].flag = 0; } sort(p+1,p+m+1,cmp); ans = kruskal(-1);//求最小生成树 int z = 1,temp; for(i = 1; i <= m&&z; i ++) { if(p[i].flag == 1)//删除生成树中的边 { temp = kruskal(i);//求次小生成树 if(ans == temp) z = 0; } } if(z) printf("%d\n",ans); else printf("Not Unique!\n"); } return 0; }
O(n^2+e)做法就是看了一下有的kruskal先求出整个生成树,然后先用BFS预处理出生成树上,每一个点和另外的点之间最大的长度,Max[x][y],然后枚举不在生成树的边,min(ans-Max[x][y]+w(x,y))就是次小生成树了。感觉用kruskal比较麻烦,用prim写就比较方便了,可以一边处理,一边更新Max[x][y]。下边代码用prim写的,其主要的思想就是存起他的父亲节点,用生成树里的点到父亲的最大距离,与父亲到自己的距离比较,取大。
#include <cstdio> #include <cstring> #include <map> #include <cmath> #include <algorithm> #define N 100000000 using namespace std; int p[201][201],low[201],o[201],dis[201][201],que[201],fath[201],key[201][201]; //dis数组存节点x到y的最大距离,que队列存进入生成树的节点 //fath存节点的父亲节点,key标记这条边是否在生成树上。 int Max(int a,int b) { return a > b ? a : b; } int main() { int i,j,k,n,m,t,sv,ev,w,ans,minz,temp; scanf("%d",&t); while(t--) { memset(p,0,sizeof(p)); memset(o,0,sizeof(o)); memset(dis,0,sizeof(dis)); memset(key,0,sizeof(key)); scanf("%d%d",&n,&m); for(i = 1; i <= n; i ++) { for(j = 1; j <= n; j ++) p[i][j] = N; } for(i = 1; i <= m; i ++) { scanf("%d%d%d",&sv,&ev,&w); if(p[sv][ev] > w) { p[sv][ev] = w; p[ev][sv] = w; } } for(i = 1; i <= n; i ++) { low[i] = p[1][i]; } o[1] = 1; ans = 0; int top; top = 1; que[1] = 1; for(i = 1;i <= n;i ++) { fath[i] = 1; } for(i = 1; i <= n-1; i ++) { minz = N; for(j = 1; j <= n; j ++) { if(minz > low[j]&&!o[j]) { minz = low[j]; k = j; } } key[fath[k]][k] = 1; key[k][fath[k]] = 1; if(minz == N) break; o[k] = 1; ans += minz; for(j = 1; j <= top; j ++) //更新队列中的点到新加入的k的边上最大边,也就是dis数组 { dis[que[j]][k] = dis[k][que[j]] = Max(minz,dis[que[j]][fath[k]]); } que[++top] = k;//k节点加入队列 for(j = 1; j <= n; j ++) { if(p[k][j] < low[j]&&!o[j]) { low[j] = p[k][j]; fath[j] = k;//记录父亲 } } } temp = N; for(i = 1; i <= n; i ++) { for(j = 1; j <= n; j ++) { if(i != j&&p[i][j] != N&&!key[i][j])//枚举不在生成树的每一条边 { if(temp > ans-dis[i][j]+p[i][j]) temp = ans-dis[i][j]+p[i][j]; } } } if(temp == ans) printf("Not Unique!\n"); else printf("%d\n",ans); } return 0; }
相关文章推荐
- POJ 1679 The Unique MST(次短生成树)
- POJ 1679 The Unique MST(次小生成树)
- 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 次小生成树
- POJ 1679 The Unique MST 次小生成树
- POJ 1679 The Unique MST(次小生成树)
- POJ 1679 The Unique MST 次小生成树
- poj1679 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(次小生成树)
- POJ - 1679 The Unique MST (次小生成树)
- poj 1679 The Unique MST(次小生成树)
- POJ 1679 The Unique MST 次小生成树