判定最小生成树是否唯一,有一个简单的方法。
用kruskal写MST,当排好序后看当前要处理的边和下一条边的权值是否相同:
是的话,再看当前这条边的两个端点所对应的集合和下一条边的两个端点所对应的集合是否一致。是的话,说明加上这条边和加上下一条边连接的两个集合都一样,也就是说这两条那边的效果一样,也就是说MST不唯一。
PS:这题的图是连同的。
#include <iostream> #include<stdio.h> #include<algorithm> #include<cstring> #define maxn 100000 #define maxv 110 #define INF 100000000 using namespace std; int n ,m; typedef struct edge { int u,v; int w; } Edge; Edge e[maxn]; int fa[maxv]; int vis[maxv]; int maxe; int mst; //找到环上所有路径 int cmp(const void * a,const void *b) { Edge* aa =(Edge*)a; Edge* bb =(Edge*)b; return aa->w - bb->w; } int find(int a) { return fa[a] == a? a:fa[a] = find(fa[a]); } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d %d",&n,&m); for(int i = 0 ; i < n; i++) fa[i] = i; for(int i = 0; i < m; i++) { scanf("%d %d %d",&e[i].u,&e[i].v,&e[i].w); e[i].flag = 0; fa[e[i].u] = e[i].u; fa[e[i].v] = e[i].v; } qsort(e,m,sizeof (Edge),cmp); int cnt = 0; //已选择的边数 int ans = 0; int ans_flag = 0; for(int i = 0; i < m; i++) //生成MST { int u = e[i].u; int v = e[i].v; int fa_u = find(u); int fa_v = find(v); if(fa_u != fa_v) { if(i < m - 1) //不是最后一条边 { int j = i + 1; int u1 = e[j].u; int v1 = e[j].v; int fa_u1 = find(u1); int fa_v1 = find(v1); //两条边权值相等切连接的集合相同 if(e[j].w == e[i].w && ((fa_u == fa_u1 && fa_v == fa_v1) || (fa_u == fa_v1 && fa_v == fa_u1))) { ans_flag = 1; break; } } fa[fa_u] = fa_v; ans+=e[i].w; cnt++; } if(cnt == n - 1) break; } if(!ans_flag)printf("%d\n",ans); else printf("Not Unique!\n"); } return 0; }