给定一张图,和S,T,你要求一条从S到T的路径使得路上的最大边和最小边的比值最小
n<=500,m<=5000
题解:枚举最小的边,然后从小到大加边并用并查集维护连通性.
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define INF 2000000000 using namespace std; 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; } int ans1=INF,ans2=1; int n,m,S,T; struct edge{ int from,to,w; }e[5005]; int s[505]; bool cmp(edge x,edge y){return x.w<y.w;} int getfa(int x){return s[x]==x?x:s[x]=getfa(s[x]);} int gcd(int a,int b){return b==0?a:gcd(b,a%b);} int main() { n=read();m=read(); for(int i=1;i<=m;i++) { e[i].from=read();e[i].to=read();e[i].w=read(); }S=read();T=read(); sort(e+1,e+m+1,cmp); int j; for(int i=1;i<=m;i++) { for(j=1;j<=n;j++) s[j]=j; for(j=i;j<=m;j++) { int x=getfa(e[j].from),y=getfa(e[j].to); if(x!=y) s[x]=y;if(getfa(S)==getfa(T))break; } if(j<=m) if((double)e[j].w/e[i].w<(double)ans1/ans2)ans1=e[j].w,ans2=e[i].w; } if(ans1==INF)return 0*puts("IMPOSSIBLE"); int x=gcd(ans1,ans2);ans1/=x;ans2/=x; if(ans2==1)printf("%d ",ans1); else printf("%d/%d ",ans1,ans2); return 0; }