Kruskal演算法-HDU1863暢通工程
阿新 • • 發佈:2018-11-20
連結
[http://acm.hdu.edu.cn/showproblem.php?pid=1863]
題意
Problem Description
省政府“暢通工程”的目標是使全省任何兩個村莊間都可以實現公路交通(但不一定有直接的公路相連,只要能間接通過公路可達即可)。經過調查評估,得到的統計表中列出了有可能建設公路的若干條道路的成本。現請你編寫程式,計算出全省暢通需要的最低成本。
Input
測試輸入包含若干測試用例。每個測試用例的第1行給出評估的道路條數 N、村莊數目M ( < 100 );隨後的 N
行對應村莊間道路的成本,每行給出一對正整數,分別是兩個村莊的編號,以及此兩村莊間道路的成本(也是正整數)。為簡單起見,村莊從1到M編號。當N為0時,全部輸入結束,相應的結果不要輸出。
Output
對每個測試用例,在1行裡輸出全省暢通需要的最低成本。若統計資料不足以保證暢通,則輸出“?”。
Sample Input
3 3
1 2 1
1 3 2
2 3 4
1 3
2 3 2
0 100
Sample Output
3
?
分析
Kruskal求最小生成樹
程式碼
#include<iostream> #include<algorithm> using namespace std; int par[1000];//祖先 int r[1000];//祖先的等級 typedef struct{//a到b以及距離 int a,b,price; }node; node a[1000]; bool cmp(node &x,node &y){ return x.price<y.price; } void init(int n){ for(int i=1;i<=n;i++){ par[i]=i; r[i]=1;//剛開始祖先是自己,祖先等級是1 } } int find(int x){ if(x==par[x]) return par[x];//如果祖先是自己返回 else{ par[x]=find(par[x]); return par[x];//祖先是它祖先的祖先 } } void merge(int u,int v){//合併二者的祖先 int f1=find(u); int f2=find(v); if(r[f1]<r[f2]){//如果u的祖先等價低於v的祖先就等級優先 par[f1]=f2; } else{//否則相反 par[f2]=f1; if(r[f1]==r[f2]) r[f1]++; //如果祖先等級相同優先前者等級加1 } } int Kruskal(int n,int m){ int edge=0,sum=0; sort(a+1,a+n+1,cmp);//對所有邊按距離從小到大排序 for(int i=1;i<=n&&edge!=m-1;i++){//當求到m-1條邊說明已經聯通 if(find(a[i].a)!=find(a[i].b)){//對每條邊找祖先如果不同說明沒聯通可以合併祖先 merge(a[i].a,a[i].b); sum+=a[i].price;//總路程加這條邊的距離 edge++;//統計邊數 } } if(edge<m-1) sum=-1;//如果邊少於m-1說明是無法聯通的 return sum; } int main() { int n,m,ans; //freopen("in.txt","r",stdin); while(cin>>n>>m&&n){ init(m); for(int i=1;i<=n;i++) { cin>>a[i].a>>a[i].b>>a[i].price; } ans=Kruskal(n,m); if(ans==-1) cout<<"?\n"; else cout<<ans<<endl; } return 0; }