BZOJ-1050 [HAOI2006]旅行comf(並查集+Kruskal演算法)
阿新 • • 發佈:2020-12-05
題目描述
給一個無向圖,\(n(n\leq 500)\) 個點,\(m(m\leq 5000)\) 條邊,每條邊有一個權值 \(v_i(v_i\leq 30000)\)。給兩個頂點\(S\) 和 \(T\) ,求一條路徑,使得 \(S\rightarrow T\) 路徑上最大邊和最小邊的比值最小。如果 \(S\) 和 \(T\) 之間沒有路徑,輸出 IMPOSSIBLE
,否則輸出這個比值。
分析
列舉最小邊權,再把比它邊權大的邊依次加入到圖中,直到 \(S\) 和 \(T\) 連通,記錄最大邊和最小邊的比值,列舉更新答案。
程式碼
#include<bits/stdc++.h> using namespace std; const double INF=0x3f3f3f3f; const int N=510,M=5010; int n,m,fa[N]; struct Edge { int u,v,w; }edge[M<<1]; bool cmp(Edge A,Edge B) { return A.w<B.w; } int get(int x) { if(fa[x]==x) return x; return fa[x]=get(fa[x]); } int main() { cin>>n>>m; for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) { scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].w); int fx=get(edge[i].u),fy=get(edge[i].v); if(fx!=fy) fa[fx]=fy; } int S,T; cin>>S>>T; if(get(S)!=get(T)) { puts("IMPOSSIBLE"); return 0; } sort(edge+1,edge+1+m,cmp); int fz,fm; double ans=INF; for(int i=1;i<=m;i++) { int pos; bool flag=false; for(int j=1;j<=n;j++) fa[j]=j; for(int j=i;j<=m;j++) { int fx=get(edge[j].u),fy=get(edge[j].v); if(fx!=fy) fa[fx]=fy; if(get(S)==get(T)) { flag=true; pos=j; break; } } if(flag) { double temp=1.0*edge[pos].w/edge[i].w; if(temp<ans) { int gcd=__gcd(edge[pos].w,edge[i].w); fz=edge[pos].w/gcd; fm=edge[i].w/gcd; ans=temp; } } } if(fm==1) printf("%d\n",fz); else printf("%d/%d\n",fz,fm); return 0; }