给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000)。给你两个顶点S和T,求一条路径,使得路径上最大边和最小边的比值最小。如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个比值,如果需要,表示成一个既约分数。 备注: 两个顶点之间可能有多条路径。
标签:
给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000)。给你两个顶点S和T,求一条路径,使得路径上最大边和最小边的比值最小。如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个比值,如果需要,表示成一个既约分数。 备注: 两个顶点之间可能有多条路径。
第一行包含两个正整数,N和M。 下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向公路,车辆必须以速度v在该公路上行驶。 最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比最小的路径。s和t不可能相同。
如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。
思路很像最小生成树。
先将边按照权值从小到大排序。
枚举最小边,将其他边按顺序依次加进去,直到s和t属于一个集合,用并查集维护。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define maxn 505 #define maxm 5005 using namespace std; struct data{int x,y,z;}a[maxm]; int n,m,s,t,mn,mx,p[maxn]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline bool cmp(data a1,data a2) { return a1.z<a2.z; } inline int find(int x) { return p[x]==x?x:p[x]=find(p[x]); } inline void merge(int x,int y) { int fx=find(x),fy=find(y); if (fx!=fy) p[fx]=fy; } inline int gcd(int x,int y) { return y?gcd(y,x%y):x; } int main() { n=read();m=read(); F(i,1,m){a[i].x=read();a[i].y=read();a[i].z=read();} sort(a+1,a+m+1,cmp); s=read();t=read(); F(i,1,m) { F(j,1,n) p[j]=j; merge(a[i].x,a[i].y); int tmp=i; while (tmp<m&&find(s)!=find(t)) { tmp++; merge(a[tmp].x,a[tmp].y); } if (find(s)!=find(t)) continue; if (tmp>m) tmp=i; if (!mx||(a[tmp].z*1.0/a[i].z<mx*1.0/mn)) { mx=a[tmp].z; mn=a[i].z; } } if (!mx) printf("IMPOSSIBLE\n"); else if (mx%mn==0) printf("%d\n",mx/mn); else { int tmp=gcd(mx,mn); printf("%d/%d\n",mx/tmp,mn/tmp); } }
标签:
原文地址:http://blog.csdn.net/aarongzk/article/details/50641514