次最小生成樹 模版
阿新 • • 發佈:2017-08-19
define ios truct rep com mem num 代碼 div 計算map[i][j](最小生成樹以外存在的邊) 與 maxd[i][j](最小生成樹上最長的邊)
差值,求出最小的來,w(T)再加上最小的差值就是次小生成樹了。
次小生成樹(轉)
轉載(http://www.cnblogs.com/z360/p/6875488.html)所謂次小生成樹,顧名思義就是從生成樹中取出的第二小的生成樹。
我們在前面已經說過最小生成樹的概念及代碼實現了,所以接下來要說的次小生成樹應該比較簡單理解了。
求次小生成樹的兩種方法
1:首先求出最小生成樹T,然後枚舉最小生成樹上的邊,計算除了枚舉的當前最小
生成樹的邊以外的所有邊形成的最小生成樹Ti,然後求最小的Ti就是次小生成樹。
2:首先計算出最小生成樹T,然後對最小生成樹上任意不相鄰的兩個點 (i,j)
添加最小生成樹以外的存在的邊形成環,然後尋找i與j之間最小生成樹上最長的邊刪去,
差值,求出最小的來,w(T)再加上最小的差值就是次小生成樹了。
給定一個圖,詢問該圖的最小生成樹與次小生成樹是否一致。
Kruscal實現版:
代碼:
//Gang #include<iostream> #include<cstring> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cmath> #defineFOR(x,y,z) for(int x=y;x<=z;x++) #define REP(x,y,z) for(int x=y;x>=z;x--) #define ll long long using namespace std; int t,n,m,fa[10000],num,ans[10000]; int tot,bns,k,answer=99999999; struct node { int x,y,z; } e[101*101]; int cmp(node a,node b) { return a.z<b.z; } int find(int x) {int p,temp; p=x; while(fa[x]!=x) { x=fa[x]; } while(x!=p) { temp=fa[p]; fa[p]=x; p=temp; } return x; } int main() { scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); tot=0,bns=0; answer=99999999; memset(fa,0,sizeof(fa)); memset(ans,0,sizeof(ans)); FOR(i,1,m) scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z); sort(e+1,e+m+1,cmp); FOR(i,1,n)fa[i]=i; FOR(i,1,m) { int dx=find(e[i].x),dy=find(e[i].y); if(dx!=dy) { tot++; fa[dx]=dy; ans[tot]=i; bns+=e[i].z; } if(tot==n-1)break; } FOR(i,1,tot) { k=0; num=0; FOR(j,1,n) fa[j]=j; sort(e+1,e+m+1,cmp); FOR(j,1,m) { if(j==ans[i])continue; int dx=find(e[j].x),dy=find(e[j].y); if(dx!=dy) { fa[dx]=dy; num++; k+=e[j].z; } if(num==n-1)break; } if(num==n-1)answer=min(k,answer); } if(answer==bns)printf("Not Unique!\n"); else printf("%d\n",bns); } return 0; }
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; }
次最小生成樹 模版