UVA-10462 Is There A Second Way Left?
阿新 • • 發佈:2018-11-02
給出圖,要求是否有生成樹,是否有次小生成樹,輸出次小生成樹花費
因為給出的圖有重邊,所以不能用prim求次小,改用kruskal
先用kruskal求出最小生成樹,並記錄所用邊
接下來列舉刪去所用邊,再生成一次最小生成樹,其中最小的就是次小生成樹
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> using namespace std; typedef long long ll; const int N=100+10; const int M=200+10; const int INF=0x7f7f7f7f; struct Edge { int u,v,w; bool operator < (const Edge &a) const { return w<a.w; } }edge[M]; int tot; void addedge(int u,int v,int w) { edge[tot].u=u; edge[tot].v=v; edge[tot++].w=w; } int uf[N]; int find(int u) { if(uf[u]==-1) return u; return uf[u]=find(uf[u]); } int used[N]; void solve(int n,int kase) { printf("Case #%d : ",kase); int ans1=0; bool flag=false; sort(edge,edge+tot); memset(uf,-1,sizeof(uf)); int cnt=0; for(int i=0;i<tot;i++) { int u=edge[i].u; int v=edge[i].v; int w=edge[i].w; int ru=find(u); int rv=find(v); if(ru!=rv) { ans1+=w; used[cnt]=i; cnt++; uf[ru]=rv; if(cnt==n-1) { flag=true; break; } } } if(!flag&&n>1) { printf("No way\n"); return; } int ans2=INF; for(int k=0;k<n-1;k++) { cnt=0; int t=0; flag=false; memset(uf,-1,sizeof(uf)); for(int i=0;i<tot;i++) { if(i==used[k]) continue; int u=edge[i].u; int v=edge[i].v; int w=edge[i].w; int ru=find(u); int rv=find(v); if(ru!=rv) { t+=w; cnt++; uf[ru]=rv; if(cnt==n-1) { flag=true; break; } } } if(flag) ans2=min(ans2,t); } if(ans2==INF) printf("No second way\n"); else printf("%d\n",ans2); } int main() { int T,kase=0; int n,m; int a,b,c; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); tot=0; for(int i=0;i<m;i++) { scanf("%d%d%d",&a,&b,&c); addedge(a,b,c); } solve(n,++kase); } return 0; }