[bzoj1050] [HAOI2006]旅行comf

给定一张图,和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\n",ans1);
    else printf("%d/%d\n",ans1,ans2);
    return 0;
}

 

posted @ 2017-03-01 17:38  FallDream  阅读(227)  评论(0编辑  收藏  举报