bzoj1050 旅行comf(并查集)
题意:
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不可能相同。
1<N<=500,1<=x,y<=N,0<v<30000,0<M<=5000
Output
如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一
个既约分数。
思路:
可以排序后枚举最小边,然后暴力最大边,类似克鲁斯卡尔
/* *********************************************** Author :devil ************************************************ */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <stdlib.h> #define inf 0x3f3f3f3f #define LL long long #define rep(i,a,b) for(int i=a;i<=b;i++) #define dec(i,a,b) for(int i=a;i>=b;i--) #define ou(a) printf("%d\n",a) #define pb push_back #define mkp make_pair template<class T>inline void rd(T &x){char c=getchar();x=0;while(!isdigit(c))c=getchar();while(isdigit(c)){x=x*10+c-'0';c=getchar();}} #define IN freopen("in.txt","r",stdin); #define OUT freopen("out.txt","w",stdout); using namespace std; const int mod=1e9+7; const int N=5e3+10; struct wq { int u,v,w; }a[N]; bool cmp(wq a,wq b) { return a.w<b.w; } int n,m,x,y,pre[510],a1,a2,j; bool flag; int Find(int x) { return x==pre[x]?x:pre[x]=Find(pre[x]); } int main() { rd(n),rd(m); rep(i,1,m) rd(a[i].u),rd(a[i].v),rd(a[i].w); sort(a+1,a+m+1,cmp); rd(x),rd(y); rep(i,1,m) { rep(j,1,n) pre[j]=j; for(j=i;j<=m;j++) { int fa=Find(a[j].u),fb=Find(a[j].v); if(fa==fb) continue; pre[fa]=fb; if(Find(x)==Find(y)) break; } if((i==1)&&(Find(x)!=Find(y))) { printf("IMPOSSIBLE\n"); flag=1; break; } if(Find(x)!=Find(y)) break; if(a1*a[i].w>=a2*a[j].w) a1=a[j].w,a2=a[i].w; } if(!flag) { int tmp=__gcd(a1,a2); if(tmp==a2) printf("%d\n",a1/a2); else printf("%d/%d\n",a1/tmp,a2/tmp); } return 0; }