什么是次小成成树:
比最小生成树大一点的就是次小生树了,也就是第二小的生成树;可以用次小生成树来判断最小生成树是否唯一,如果次小生成树和最小生成树相等,那就说明不唯一;
但是突然发现产生一个问题:尼玛啊?次小生成树都等于最小生成树了还叫次小生成树吗?于是我去百度了一番。。发现对次小生成树并没有明确的定义。。那如果最小生成树不唯一,那次小生成树是另一种姿势的最小生成树还是一定要比最小生成树大的树呢……处女座表示伤不起。
反正题目要求哪种就求哪种,然后大家都说这是最小生成树 !就是这样!
神经病0-0~~~~~~~啊啊啊 !!!
通常求次小生成树通常都是建立在先求出的MST上的,根据MST的定义,在MST上加不属于一条MST的边一定会形成环;
然后删除此时环上第二大的边(最大的为新加的,别告诉我什么两个边的值是相等的情况!!啊啊!!),就可以得到一个新的生成树了,枚举所有的不在MST上的边,重复此操作,即可求得次小生成树。
当然,实现起来并不需要这么麻烦,有更好的实现方法:再求MST时,用数组Max[i][j]记录MST中i到j的最大边权;
然后枚举所有的边(u,v),如果它不在MST中,就替换掉Max[i][j];显然这个操作明不会影响图的连通。
minc=min(minc,ans+mp[i][j]-Max[i][j]);代码(可以当作模版):
/* *********************************************** Author :angon ************************************************ */ #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <stack> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <math.h> #include <stdlib.h> #include <time.h> using namespace std; #define REP(i,k,n) for(int i=k;i<n;i++) #define REPP(i,k,n) for(int i=k;i<=n;i++) #define scan(d) scanf("%d",&d) #define scann(n,m) scanf("%d%d",&n,&m) #define LL long long #define maxn 110 #define N 100000000 int mp[maxn][maxn]; int used[maxn][maxn]; int Max[maxn][maxn]; int vis[maxn],lowc[maxn],pre[maxn]; int m,n; int Prim() { memset(Max,0,sizeof(Max)); memset(used,0,sizeof(used)); memset(vis,0,sizeof(vis)); for(int i=0;i<=n;i++) { pre[i]=1; lowc[i]=mp[1][i]; } lowc[1]=0; vis[1]=1; pre[1]= -1; int ans=0; for(int i=2;i<=n;i++) { int minc=N,p=-1; for(int j=1;j<=n;j++) if(!vis[j] && lowc[j]<minc) { minc=lowc[j]; p=j; } if(minc==N) return -1; ans+=minc; vis[p]=1; used[p][pre[p]]=used[pre[p]][p]=1; for(int j=1;j<=n;j++) { if(vis[j]) Max[p][j]=Max[j][p]=max(Max[j][pre[p]],lowc[p]); //lowc[p]其实就是mp[pre[p]][p] if(!vis[j] && mp[p][j] < lowc[j]) { lowc[j]=mp[p][j]; pre[j]=p; } } } return ans; } int smst() { int minc=N,ans=Prim(); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) if(mp[i][j]!=N && !used[i][j]) minc=min(minc,ans+mp[i][j]-Max[i][j]); if(minc==N) return -1; return minc; } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int t; scan(t); while(t--) { int u,v,w; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) mp[i][j]=mp[j][i]=N; while(m--) { scanf("%d%d%d",&u,&v,&w); mp[u][v]=mp[v][u]=w; } int ans=Prim(); if(ans==smst()) printf("Not Unique!\n"); else printf("%d\n",ans); } return 0; }