1. 程式人生 > >[BZOJ]1050 旅行comf(HAOI2006)

[BZOJ]1050 旅行comf(HAOI2006)

速度 上界 輸出 個數 分數 gis %d 更多 eof

  圖論一直是小C的弱項,相比其它題型,圖論的花樣通常會更多一點,套路也更難捉摸。

Description

  給你一個無向圖,N(N<=500)個頂點, M(M<=5000)條邊,每條邊有一個權值Vi(Vi<30000)。給你兩個頂點S和T,求一條路徑,使得路徑上最大邊和最小邊的比值最小。如果S和T之間沒有路徑,輸出”IMPOSSIBLE”,否則輸出這個比值,如果需要,表示成一個既約分數。 備註: 兩個頂點之間可能有多條路徑。

Input

  第一行包含兩個正整數,N和M。下來的M行每行包含三個正整數:x,y和v。表示景點x到景點y之間有一條雙向公路,車輛必須以速度v在該公路上行駛。最後一行包含兩個正整數s,t,表示想知道從景點s到景點t最大最小速度比最小的路徑。s和t不可能相同。

Output

  如果景點s到景點t沒有路徑,輸出“IMPOSSIBLE”。否則輸出一個數,表示最小的速度比。如果需要,輸出一個既約分數。

Sample Input

  3 3
  1 2 10
  1 2 5
  2 3 8
  1 3

Sample Output

  5/4

HINT

  1<N<=500,1<=x,y<=N,0<v<30000,0<M<=5000

Solution

  看到最大和最小值我們就可以感覺到肯定不能直接走,然後很自然地想到了排序。

  這種圖論的題型常常要求我們逆向思考,我們不是找一條路徑去更新答案,而是枚舉一個答案看它能否構成路徑。

  於是我們枚舉路徑中的最小的那條邊,從小到大加邊,直到S和T連通,

  說明存在一條S到T的路徑。用最後加入的這條邊和枚舉的最小邊更新答案。

  判連通性用並查集即可。

  時間復雜度O(m^2)

  在黃學長博客裏還看到一個比較妙的解法分享一下:

    技術分享

  理論復雜度是一樣的,但實際遠小於上界。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define MN 505
#define MM 5005
#define INF 0x3FFFFFFF
using
namespace std; struct edge{int x,y,z;}b[MM]; int fa[MN]; int n,m,S,T,ans1,ans2,g; inline int read() { int n=0,f=1; char c=getchar(); while (c<0 || c>9) {if(c==-)f=-1; c=getchar();} while (c>=0 && c<=9) {n=n*10+c-0; c=getchar();} return n*f; } int getf(int x) {return fa[x]?fa[x]=getf(fa[x]):x;} inline void gather(int x,int y) {if (x!=y) fa[x]=y;} int gcd(int x,int y) {return y?gcd(y,x%y):x;} bool cmp(const edge& a,const edge& b) {return a.z<b.z;} int main() { register int i,j; n=read(); m=read(); for (i=1;i<=m;++i) b[i].x=read(),b[i].y=read(),b[i].z=read(); S=read(); T=read(); sort(b+1,b+m+1,cmp); ans1=INF; ans2=1; for (i=1;i<=m;++i) { memset(fa,0,sizeof(fa)); for (j=i;j<=m;++j) { gather(getf(b[j].x),getf(b[j].y)); if (getf(S)==getf(T)) break; } if (j>m) break; if ((double)b[j].z/b[i].z<(double)ans1/ans2) ans1=b[j].z,ans2=b[i].z; } if (i==1) return 0*printf("IMPOSSIBLE"); g=gcd(ans1,ans2); ans1/=g; ans2/=g; if (ans2==1) printf("%d",ans1); else printf("%d/%d",ans1,ans2); }

Last Word

  用並查集解決圖論的問題也是常見的思路。

  小C會告訴你迷之RE是因為並查集寫錯了?

[BZOJ]1050 旅行comf(HAOI2006)