BZOJ 1050并查集+贪心
1050: [HAOI2006]旅行comf
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3333 Solved: 1851
[Submit][Status][Discuss]
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”。否则输出一个数,表示最小的速度比。
如果需要,输出一个既约分数。
Sample Input
【样例输入1】
4 2
1 2 1
3 4 2
1 4
【样例输入2】
3 3
1 2 10
1 2 5
2 3 8
1 3
【样例输入3】
3 2
1 2 2
2 3 4
1 3
4 2
1 2 1
3 4 2
1 4
【样例输入2】
3 3
1 2 10
1 2 5
2 3 8
1 3
【样例输入3】
3 2
1 2 2
2 3 4
1 3
Sample Output
【样例输出1】
IMPOSSIBLE
【样例输出2】
5/4
【样例输出3】
2
IMPOSSIBLE
【样例输出2】
5/4
【样例输出3】
2
每次看题解都会感觉题解好无赖好强 http://hzwer.com/844.html
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; inline int gcd(int a,int b) {return !b?a:gcd(b,a%b);} struct node{ int u,v,w; bool operator <(const node &B)const { return w<B.w; } }e[30008]; int f[508]; int findx(int x) {return x==f[x]?f[x]:f[x]=findx(f[x]);} int main(){ int S,T; int n,m; int ansm=-1,ansz=-1; scanf("%d%d",&n,&m); for(int i=0;i<m;++i) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); scanf("%d%d",&S,&T); int st=0; sort(e,e+m); while(st<m){ int mx=-1,mi=-1; for(int i=1;i<=n;++i) f[i]=i; int x=st; for(;x<m;++x){ int u=findx(e[x].u),v=findx(e[x].v),w=e[x].w; f[u]=v; if(findx(S)==findx(T)) { mx=w; break; } } if(mx==-1) { if(ansm==-1) {puts("IMPOSSIBLE");return 0;} else break; } for(int i=1;i<=n;++i) f[i]=i; for(;x>=0;--x) { int u=findx(e[x].u),v=findx(e[x].v),w=e[x].w; f[u]=v; if(findx(S)==findx(T)) { mi=w; break; } } st=x+1; int tt=gcd(mi,mx); mi/=tt; mx/=tt; if(ansm==-1||ansm*mi>ansz*mx) { ansm=mx; ansz=mi; } } if(ansz==1) printf("%d\n",ansm); else printf("%d/%d",ansm,ansz); }