http://poj.org/problem?id=167 9
問最小生成樹是否唯一 ? ?其實就是問次小生成樹是否等于最小生成樹
思路:
1 ?Kruskal 求最小生成樹MIN 記錄哪些邊用了 哪些沒有用 并建樹
2 ?dfs 從每一點開始 求最小生成樹上任意兩點間的最長邊
3 枚舉沒用過的邊加入的情況 取(MIN+此邊權-樹中此兩點間最長邊權) ?最小的那一個就是次小生成樹
代碼及其注釋:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<map> #include<queue> #include<cmath> #define LL long long using namespace std; const int N=105; struct node { struct tt *next; }mem[N]; struct tt { int j,k; struct tt *next; }; struct ss { bool used; int i,j,d; }side[N*N]; int Mi_j[N][N]; int f[N]; void build(int i,int j,int d)//建樹 { struct tt *t=new tt; t->j=j; t->k=d; t->next=mem[i].next; mem[i].next=t; } void Dele(int n)//刪樹 { for(int i=1;i<=n;++i) mem[i].next=NULL; } inline int findx(int x)//并查集 { if(f[x]!=x) f[x]=findx(f[x]); return f[x]; } int Kruskal(int n,int m)//求最小生成樹 { int sum=0; for(int i=1;i<=n;++i) f[i]=i; for(int l=0;l<m;++l) { int x=side[l].i; int y=side[l].j; if(findx(x)!=findx(y)) { build(x,y,side[l].d);//建樹 build(y,x,side[l].d); f[findx(x)]=y; sum+=side[l].d; side[l].used=true;//標記是否用過 } } return sum; } void dfs(int st,int x,int pre,int M) { if(M!=0) Mi_j[st][x]=max(Mi_j[st][x],M);//求st到x最長邊權 struct tt *t=mem[x].next; while(t!=NULL) { if(t->j!=pre) { dfs(st,t->j,x,max(M,t->k)); } t=t->next; } } int Fmtree(int n,int m,int MIN) { int mtree=MIN+1; memset(Mi_j,0,sizeof(Mi_j)); for(int i=1;i<=n;++i) dfs(i,i,0,0);//求樹中任意兩點間的最長邊權 for(int l=0;l<m;++l) { if(side[l].used==true) continue; int x=side[l].i; int y=side[l].j; mtree=min(mtree,MIN+side[l].d-Mi_j[x][y]);//枚舉 } return mtree; } int main() { //freopen("data.txt","r",stdin); int T; scanf("%d",&T); while(T--) { int n,m; scanf("%d %d",&n,&m); for(int i=0;i<m;++i) { scanf("%d %d %d",&side[i].i,&side[i].j,&side[i].d); side[i].used=false; } int MIN=Kruskal(n,m); if(MIN==Fmtree(n,m,MIN)) printf("Not Unique!\n"); else printf("%d\n",MIN); Dele(n); } return 0; }
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
