1. 程式人生 > 實用技巧 >【PAT頂級】1001 Battle Over Cities - Hard Version (35分)(最小生成樹Prim演算法)

【PAT頂級】1001 Battle Over Cities - Hard Version (35分)(最小生成樹Prim演算法)

題意:輸入兩個正整數N(<=500)和M,分別表示圖中點的數量和邊的數量,接著輸入M行,每行包括四個數,分別代表一條邊的兩個端點和修通這條路的花費以及識別符號,識別符號為1說明這條路暢通,識別符號為0說明這條路不能使用。如果這張圖中其中一個點失效,那麼所有和這個點連線的路徑都會不能使用(且因為這個點的失效,這條路無法修通),此時需要修通一些(可能不需要修通)路徑試得剩餘N-1個點聯通。如果有多個這樣的點,以序號升序輸出,沒有則輸出0。

AAAAAccepted code:

 1 #define HAVE_STRUCT_TIMESPEC
 2 #include<bits/stdc++.h>
 3
using namespace std; 4 int dis[507][507]; 5 int res[507]; 6 bool vis[507]; 7 int n,m; 8 int d[507]; 9 void mst(int v){ 10 memset(vis,0,sizeof(vis)); 11 int s=1+v;//以失效的點的下一個點作為起點 12 if(s>n) 13 s=1;//失效點為n的時候,以1為起點 14 for(int i=1;i<=n;++i) 15 d[i]=dis[i][s]; 16 vis[v]=vis[s]=1
; 17 int nex=0; 18 int num=n-2;//去掉失效點和起點一共有n-2個點 19 while(num--){ 20 int mn=1e9; 21 for(int i=1;i<=n;++i) 22 if(!vis[i]&&mn>d[i]){ 23 mn=d[i]; 24 nex=i; 25 } 26 if(mn==1e9){ 27 res[v]=1e9;
28 break; 29 } 30 res[v]+=mn; 31 vis[nex]=1; 32 for(int i=1;i<=n;++i) 33 if(!vis[i]&&d[i]>dis[i][nex])//更新未被訪問過的點到已經加入集合中的點的最短路徑 34 d[i]=dis[i][nex]; 35 } 36 } 37 int main(){ 38 ios::sync_with_stdio(false); 39 cin.tie(NULL); 40 cout.tie(NULL); 41 for(int i=1;i<=500;++i) 42 for(int j=1;j<=500;++j) 43 dis[i][j]=1e9; 44 cin>>n>>m; 45 for(int i=1;i<=m;++i){ 46 int c1,c2,cost,status; 47 cin>>c1>>c2>>cost>>status; 48 if(status==0) 49 dis[c1][c2]=dis[c2][c1]=cost; 50 else 51 dis[c1][c2]=dis[c2][c1]=0; 52 } 53 int mx=0; 54 for(int i=1;i<=n;++i){ 55 mst(i); 56 mx=max(mx,res[i]); 57 } 58 if(mx==0) 59 cout<<0; 60 else{ 61 int flag=0; 62 for(int i=1;i<=n;++i){ 63 if(flag&&res[i]==mx) 64 cout<<" "<<i; 65 else if(res[i]==mx){ 66 cout<<i; 67 flag=1; 68 } 69 } 70 } 71 return 0; 72 }