次小生成树是权值第二小的生成树,可能与最小生成树权值相等。对于最小生成树上任意两点,如果只能经过最小生成树上的边,路径都是唯一的。而次小生成树可以由一条非最小生成树上的边换取一条最小生成树的边而得到。所以在生成最小生成树的同时,记录最小生成树上任意两点路径中最长的路径即可。
#include <iostream> using namespace std ; int graph[110][110], value[110][110] ; //value[i][j]表示最小生成树中i到j最长的路径 int pre[110] ; //pre[i]表示i的前驱结点 bool visit[110] ; //标志结点是否被访问 int n, m, t, i, j, k, sum, Min, a, b ; void Prim() { sum=0 ; visit[1]=true ; for(i=1; i<n; i++) { j=1 ; while(visit[j]) j++ ; for(Min=j++; j<=n; j++) if(!visit[j]&&graph[Min][0]>graph[j][0]) Min=j ; sum+=graph[Min][0] ; for(j=1; j<=n; j++) if(visit[j])//保存j与Min间最长的边权值 { if(value[j][pre[Min]]<graph[Min][0]) { value[j][Min]=graph[Min][0]; value[Min][j]=value[j][Min] ; } else { value[j][Min]=value[j][pre[Min]]; value[Min][j]=value[j][Min] ; } } visit[Min]=true ; for(j=1; j<=n; j++) if(!visit[j]&&graph[j][Min]<graph[j][0]) { graph[j][0]=graph[j][Min] ; pre[j]=Min ; } } } void SecondMST() { a=INT_MAX ; for(i=1; i<=n; i++) for(j=1; j<=n; j++) if(i!=j && pre[i]!=j && pre[j]!=i) if(a>sum-value[i][j]+graph[i][j]&&graph[i][j]<INT_MAX) a=sum-value[i][j]+graph[i][j]; } int main() { scanf("%d", &t) ; while(t--) { scanf("%d%d", &n, &m) ; for(i=0; i<=n; i++) for(j=0; j<=n; j++) graph[i][j]=INT_MAX, value[i][j]=0 ; for(i=0; i<m; i++) { scanf("%d%d%d",&a,&b, &j) ; graph[a][b]=graph[b][a]=j ; } for(i=1; i<=n; i++) visit[i]=false, pre[i]=1, graph[i][0]=graph[i][1] ; Prim() ; SecondMST() ; if(a==sum) printf("Not Unique!\n"); else printf("%d\n",sum) ; } return 0 ; }