题目大意是判断一个图的最小生成树是否唯一
求出次小生成树,若次小生成树的权值不等于最小生成树,则唯一,若相等,则不唯一
#include <stdio.h> #include <string.h> int map[110][110],max[110][110],p[110],low[110],n,m,vis[110][110]; /*max[i][j]表示最小生成树中从i到j的路径中最长的边,map是边,p[i]是prim每次选进去的边一个节点(在之前选进去的集合中的节点) vis[i][j]若为0,表示i到j无边,等于一表示有边但未选入最小生成树,等于2表示选入了最小生成树*/ int MAX(int a,int b) { if(a>b) return a; else return b; } int prim(int u) { int i,min,v,j,cost=0; for(j=1;j<=n;j++) { low[j]=map[j][u]; p[j]=u; } low[u]=-1; for(j=1;j<=n-1;j++) { min=50000; for(i=1;i<=n;i++) { if(low[i]!=-1&&min>low[i]) { min=low[i]; v=i; } } low[v]=-1; cost+=min; vis[v][p[v]]=vis[p[v]][v]=2;/*在生成树中,所以改为2*/ for(i=1;i<=n;i++) if(i!=v) max[i][v]=max[v][i]=MAX(min,max[i][p[v]]);/*每次选入一个边都更新一遍max*/ for(i=1;i<=n;i++) { if(low[i]!=-1&&map[v][i]<low[i]) { low[i]=map[v][i]; p[i]=v; } } } return cost; } int main() { int t,i,j,k,x,y,min,sum,w; scanf("%d",&t); for(i=0;i<t;i++) { min=50000; scanf("%d%d",&n,&m); memset(max,0,sizeof(max));/*刚开始时初始为0*/ memset(vis,0,sizeof(vis)); for(j=1;j<=n;j++) for(k=1;k<=n;k++) map[j][k]=50000; for(j=0;j<m;j++) { scanf("%d%d%d",&x,&y,&w); map[x][y]=map[y][x]=w; vis[x][y]=vis[y][x]=1; } sum=prim(1); for(j=1;j<=n;j++) for(k=1;k<=n;k++) if(vis[j][k]==1&&min>sum+map[j][k]-max[j][k]) /*将不在生成树中的边依次加入生成树,形成一个环,去掉环上原生成树中的最大边形成一棵较大的生成树*/ min=sum+map[j][k]-max[j][k]; if(min!=sum) printf("%d\n",sum); else printf("Not Unique!\n"); } return 0; }