解題思路:三種輸出狀況,很簡單,但用prim()寫就WA到底,感受全部狀況都考慮了啊,多是定點不必定是1到N,因此會出現bug.因此建議仍是用kruskal寫簡單一些,別怕超時,大膽寫.spa
kruskal代碼以下:
code
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 110; const int M = 220; const int INF = 1000000000; int n, m, T, ans1, ans2, ise[N], f[N]; struct edge { int u, v, cost; }e[M]; bool cmp( edge a, edge b ) { return a.cost < b.cost; } int find ( int x ) { return f[x] == x ? x: f[x] = find(f[x]); } int Kru() { int ans = 0, num = 0, id = 0; for ( int i = 1; i <= n; ++i ) f[i] = i; for ( int i = 0; i < m; ++i ) { int x = e[i].u; int y = e[i].v; int a = find(x); int b = find(y); if ( a != b ) ise[id++] = i, f[a] = b, ans += e[i].cost; } for ( int i = 1; i <= n; ++i ) if ( i == find(i) ) num++; if ( num > 1 ) return INF; else return ans; } int Kru_1( int del ) { int ans = 0, num = 0; for ( int i = 1; i <= n; ++i ) f[i] = i; for ( int i = 0; i < m; ++i ) { if ( i == del ) continue; int x = e[i].u; int y = e[i].v; int a = find(x); int b = find(y); if ( a != b ) f[a] = b, ans += e[i].cost; } for ( int i = 1; i <= n; ++i ) if ( i == find(i) ) num++; if ( num > 1 ) return INF; else return ans; } int main() { int idx = 1; scanf("%d", &T); while ( T-- ) { scanf("%d%d", &n, &m); for ( int i = 0; i < m; ++i ) scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].cost); sort( e, e+m, cmp ); ans1 = Kru(), ans2 = INF; printf("Case #%d : ", idx++); if ( ans1 == INF ) { printf("No way\n"); continue; } for ( int i = 0; i < n-1; ++i ) { int x = ise[i]; ans2 = min( ans2, Kru_1(x) ); } if ( ans2 == INF ) printf("No second way\n"); else printf("%d\n", ans2); } return 0; }
另外附上我WA的prim():get
</pre><pre name="code" class="cpp">#include<stdio.h> #include<string.h> #include<algorithm> #define INF 0x3f3f3f3f using namespace std; struct stu{ int x,y,c; }; stu num[210]; int n,m; int map[110][110]; int inMST[110][110]; int MST[110][110]; int vis[110]; int per[110]; int low[110]; int see[110][110]; void inin(){ for(int i=1;i<=n;i++){ map[i][i]=0; for(int j=1;j<i;j++){ map[i][j]=map[j][i]=INF; } } } void getMap(){ int a,b,c; memset(see,0,sizeof(see)); for(int i=1;i<=m;i++){ scanf("%d%d%d",&a,&b,&c); num[i].x=a;num[i].y=b;num[i].c=c; see[a][b]++;see[b][a]++; if(map[a][b]>c){ map[a][b]=map[b][a]=c; } } } int slove(){ int temp,v,i,j,k,fa,sum,w,x,y; v=0;sum=INF; memset(vis,0,sizeof(vis)); memset(inMST,0,sizeof(inMST)); memset(MST,0,sizeof(MST)); for(i=1;i<=n;i++){ low[i]=map[1][i]; per[i]=1; } per[1]=0; vis[1]=1; for(i=2;i<=n;i++){ temp=INF; for(j=1;j<=n;j++){ if(!vis[j]&&low[j]<temp){ temp=low[j]; k=j; } } if(temp==INF)return -1; vis[k]=1; v+=temp; fa=per[k]; inMST[k][fa]=inMST[fa][k]=1; for(j=1;j<=n;j++){ if(j!=k&&vis[j]) MST[k][j]=MST[j][k]=max(MST[j][fa],low[k]); if(!vis[j]&&low[j]>map[k][j]){ low[j]=map[k][j]; per[j]=k; } } } for(i=1;i<=m;i++){ x=num[i].x;y=num[i].y;w=INF; if(!inMST[x][y]) w=v-MST[x][y]+num[i].c; else if(see[x][y]>1) w=v-map[x][y]+num[i].c; if(w<sum)sum=w; } return sum; } int main(){ int t,ans,k; scanf("%d",&t); k=1; while(t--){ scanf("%d%d",&n,&m); inin(); getMap(); ans=slove(); printf("Case #%d : ",k++); if(ans==-1)printf("No way\n"); else if(ans==INF) printf("No second way\n"); else printf("%d\n",ans); } return 0; }//錯誤案例 1 4 5 1 2 1 1 3 2 3 4 2 4 5 1 5 4 1 錯誤輸出6