POJ 1679 判断最小树是否唯一
生活随笔
收集整理的这篇文章主要介绍了
POJ 1679 判断最小树是否唯一
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
题意:
判断最小树是否唯一。
思路:
判断最小树是否唯一。
思路:
我用了两种方法,主要就是好久没敲了,找个水题练练手,第一种就是先一遍最小生成树,然后枚举最小生成树上的每一条边,然后取消这条边,在跑一遍最小生成树,就这样一直跑最小生成树,如果找到了一颗和之前的那个一样的,那么就是不唯一,第二种方法也是先最小树,然后枚举,在枚举的时候不是继续重新跑,而是断开当前边,把树分成两个集合<两次深搜实现>,然后在枚举这连个集合之间是否可以找到一个可以代替当前枚举的最小树的边,实现复杂度的话应该是第二种快点,但理论上也快不多少,只是为了练练手,在多说一句,第二种方法和求次小树的思路有点像,但是次小树可以再这个上面进行dp优化,其实这个题目也可以直接判断次小树是否等于最小树。好像有点说多了。
#include<stdio.h> #include<string.h> #include<algorithm>#define N 110using namespace std;typedef struct {int x ,y ,c; }EDGE;typedef struct {int to ,next; }STAR;EDGE edge[N*N]; STAR E[N*N]; int map[N][N] ,mer[N] ,mark[N]; int list[N] ,tot ,mst[N]; int L[N] ,R[N] ,ll ,rr;void add(int a, int b) {E[++tot].to = b;E[tot].next = list[a];list[a] = tot; }int finds(int x) {return x == mer[x] ? x : mer[x] = finds(mer[x]); }int minn(int x ,int y) {return x < y ? x : y; }bool camp(EDGE a ,EDGE b) {return a.c < b.c; }int MST(int n ,int m) {for(int i = 1 ;i <= n ;i ++) mer[i] = i;int Ans = 0 ,sum = 0;memset(list ,0 ,sizeof(list)) ,tot = 1;for(int i = 1 ;i <= m ;i ++){int xx = finds(edge[i].x);int yy = finds(edge[i].y);if(xx != yy) {Ans += edge[i].c ,sum ++;mer[xx] = yy;mst[sum] = i;add(edge[i].x ,edge[i].y);add(edge[i].y ,edge[i].x);}if(sum == n - 1) break;}return Ans; }void DFS1(int x) {for(int k = list[x] ;k ;k = E[k].next){int to = E[k].to;if(mark[to]) continue;mark[to] = 1;L[++ll] = to;DFS1(to);} }void DFS2(int x) {for(int k = list[x] ;k ;k = E[k].next){int to = E[k].to;if(mark[to]) continue;mark[to] = 1;R[++rr] = to;DFS2(to);} }int main () {int t ,n ,m ,i ,j ,mk;scanf("%d" ,&t);while(t--){scanf("%d %d" ,&n ,&m);for(i = 1 ;i <= n ;i ++)for(j = 1 ;j <= n ;j ++)map[i][j] = 100000000;for(i = 1 ;i <= m ;i ++){scanf("%d %d %d" ,&edge[i].x ,&edge[i].y ,&edge[i].c); int x = edge[i].x ,y = edge[i].y;map[x][y] = map[y][x] = minn(map[x][y] ,edge[i].c);}sort(edge + 1 ,edge + m + 1 ,camp);int Ans = MST(n ,m);if(m == n - 1){printf("%d\n" ,Ans);continue;}mk = 0;for(i = 1 ;i < n && !mk;i ++){memset(mark ,0 ,sizeof(mark));int l = edge[mst[i]].x ,r = edge[mst[i]].y;mark[l] = mark[r] = 1;ll = rr = 0;L[++ll] = l ,R[++rr] = r; DFS1(l) ,DFS2(r);for(int j = 1 ;j <= ll && !mk;j ++){for(int k = 1 ;k <= rr && !mk ;k ++){if(L[j] == edge[mst[i]].x && R[k] == edge[mst[i]].y || L[j] == edge[mst[i]].y && R[k] == edge[mst[i]].x)continue;if(map[L[j]][R[k]] == edge[mst[i]].c) mk = 1;}}}mk ? printf("Not Unique!\n"): printf("%d\n" ,Ans);}return 0; }
总结
以上是生活随笔为你收集整理的POJ 1679 判断最小树是否唯一的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: hdu 5020 求三点共线的组合数(容
- 下一篇: POJ 1716 区间最小点个数