题意是求最小生成树是否唯一,通过求次最小生成树的值与最小生成树的值是否相等来判断是否唯一
prime算法:因为权值有可能是0,故初始化不能赋值0

#include <iostream> #include <cstdio> #include <cstring> #define MAXM 105 #define INF 1000000000 int g[MAXM][MAXM],use[MAXM][MAXM],f[MAXM][MAXM]; int N,M,ans1,ans2; //use=1表示还没在最小生成树里的边,use=2表示在最小生成树里的边 //f[i][j]表示生成树中i到j最大权值 using namespace std; int prim()//最小生成树 { int d[MAXM],vis[MAXM],pre[MAXM]; int ans=0; memset(vis,0,sizeof(vis)); memset(pre,-1,sizeof(pre)); for(int i=0;i<MAXM;i++) d[i]=INF; d[1]=0; for(int i=1;i<=N;i++){ int p;int minc=INF; for(int j=1;j<=N;j++){ if(!vis[j]&&d[j]<minc){ minc=d[j]; p=j; } } if(pre[p]!=-1){ use[p][pre[p]]=use[pre[p]][p]=2; for(int j=1;j<=N;j++) if(vis[j]) f[p][j]=f[j][p]=max(f[j][pre[p]],g[pre[p]][p]); } if(minc==INF)return -1; ans+=d[p]; vis[p]=1; for(int j=1;j<=N;j++){ if(!vis[j]&&g[p][j]<d[j]&&g[p][j]!=-1){ d[j]=g[p][j]; pre[j]=p; } } } return ans; } int sec_Tree()//次最小生成树 { int ans=INF; for(int i=1;i<=N;i++) for(int j=1;j<=N;j++){ if(use[i][j]==1){ int a=ans1-f[i][j]+g[i][j]; if(a<ans) ans=a; } } return ans; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&N,&M); int a,b,c; memset(use,0,sizeof(use)); memset(f,0,sizeof(f)); memset(g,-1,sizeof(g)); //因为权值有可能是0,所以g初始化不能是0 for(int j=0;j<M;j++){ scanf("%d%d%d",&a,&b,&c); g[a][b]=g[b][a]=c; use[a][b]=use[b][a]=1; } ans1=prim(); ans2=sec_Tree(); if(ans1==ans2) printf("Not Unique!\n"); else printf("%d\n",ans1); } return 0; }
kruscal算法: