所谓次小生成树,顾名思义就是从生成树中取出的第二小的生成树。
我们在前面已经说过最小生成树的概念及代码实现了,所以接下来要说的次小生成树应该比较简单理解了。
求次小生成树的两种方法
1:首先求出最小生成树T,然后枚举最小生成树上的边,计算除了枚举的当前最小
生成树的边以外的所有边形成的最小生成树Ti,然后求最小的Ti就是次小生成树。
2:首先计算出最小生成树T,然后对最小生成树上任意不相邻的两个点 (i,j)
添加最小生成树以外的存在的边形成环,然后寻找i与j之间最小生成树上最长的边删去,
计算map[i][j](最小生成树以外存在的边) 与 maxd[i][j](最小生成树上最长的边)
差值,求出最小的来,w(T)再加上最小的差值就是次小生成树了。
给定一个图,询问该图的最小生成树与次小生成树是否一致。
Kruscal实现版:
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct nond{ int x,y,z; }edge[101*101]; int T,N,M,x,y,z,fa[1000],num,ans[1000]; int tot,bns,k,answer=9999999; int cmp(nond aa,nond bb){ return aa.z<bb.z; } int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]); } int main(){ cin>>T; while(T--){ cin>>N>>M; tot=0;bns=0; answer=9999999; memset(fa,0,sizeof(fa)); memset(ans,0,sizeof(ans)); for(int i=1;i<=M;i++){ cin>>x>>y>>z; edge[i].x=x; edge[i].y=y; edge[i].z=z; } sort(edge+1,edge+1+M,cmp); for(int i=1;i<=N;i++) fa[i]=i; for(int i=1;i<=M;i++){ int dx=find(edge[i].x),dy=find(edge[i].y); if(dx!=dy){ fa[dx]=dy; tot++; ans[tot]=i; bns+=edge[i].z; } if(tot==N-1) break; } for(int i=1;i<=tot;i++){ k=0;num=0; for(int j=1;j<=N;j++) fa[j]=j; sort(edge+1,edge+1+M,cmp); for(int j=1;j<=M;j++){ if(j==ans[i]) continue; int dx=find(edge[j].x),dy=find(edge[j].y); if(dx!=dy){ fa[dx]=dy; num++; k+=edge[j].z; } if(num==N-1) break; } if(num==N-1) answer=min(k,answer); } if(answer==bns) cout<<"Not Unique!"<<endl; else cout<<bns<<endl; } }
prim实现版
代码;
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int inf = 0x7fffffff; const int size = 501; int firstpath[size][size]; int secondpath[size][size]; int pre[size]; int d[size]; int tree[size]; int t=0; bool flag[size]; int V,E; int qmax(int x,int y) { if(x>y)return x; else return y; } void prime(int u) { int i,j; for(i=1;i<=V;++i) { flag[i]=false; d[i]=inf; } for(i=1;i<=V;++i) for(j=i;j<=V;++j) secondpath[i][j]=secondpath[j][i]=-1; t=0; tree[t++]=u; flag[u]=true; for(i=1;i<V;++i) { int min=inf; int k; for(j=1;j<=V;++j) { if(d[j]>firstpath[u][j]) { d[j]=firstpath[u][j]; pre[j]=u; } if(!flag[j] && d[j]<min) { min=d[j]; k=j; } } for(j=0,u=k;j<t;++j) { secondpath[tree[j]][u]=qmax(secondpath[tree[j]][pre[u]],d[u]); secondpath[u][tree[j]]=secondpath[tree[j]][u]; } firstpath[pre[u]][u]=firstpath[u][pre[u]]=inf; flag[u]=true; tree[t++]=u; } for(i=1;i<=V;++i) for(j=i+1;j<=V;++j) if(firstpath[i][j]!=inf && firstpath[i][j]==secondpath[j][i]) { printf("Yes\n"); return ; } printf("No\n"); } int main() { int i,T,j,x,y,z; scanf("%d",&T); while(T--) { scanf("%d%d",&V,&E); for(i=1;i<=V;++i) for(j=i;j<=V;++j) firstpath[i][j]=firstpath[j][i]=inf; for(i=0;i<E;++i) { scanf("%d%d%d",&x,&y,&z); firstpath[x][y]=firstpath[y][x]=z; } prime(1); } return 0; }