1050: [HAOI2006]旅行comf

题目链接:

题意:给出n个点,m条边,找出从s到t中某条路径上的最大值/最小值的比值最小,如果木有则输出不可能(英文),如果有,则输出最简分数形式

solve:

直接暴力枚举,给边进行权值排序。以某条边为最小值然后去更新能使s到达t的最大值,用并查集来判断两点是否连通

所以总的来说就是暴力+并查集(一开始头铁敲了个dfs直接T了emmm)

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
#define ll long long
#define re register
#define pb push_back
const int N=1e6+10;
void read(int &a)
{
    a=0;int d=1;char ch;
    while(ch=getchar(),ch>'9'||ch<'0')
        if(ch=='-')
            d=-1;
    a=ch^48;
    while(ch=getchar(),ch>='0'&&ch<='9')
        a=(a<<3)+(a<<1)+(ch^48);
    a*=d;
}
int f[N];
struct note{int u,v,w;}edge[N];
int getv(int v){return f[v]=v==f[v]?v:getv(f[v]);}
bool cmp(note x,note y) {return x.w<y.w;}
int gcd(int a,int b) {return !b?a:gcd(b,a%b);}
int main()
{
    int n,m;
    read(n),read(m);
    for(re int i=1;i<=n;i++) f[i]=i;
    for(re int i=1;i<=m;i++)
    {
        int x,y,w;
        read(x),read(y),read(w);
        int t1=getv(x),t2=getv(y);
        if(t1!=t2) f[t2]=t1;
        edge[i].u=x,edge[i].v=y,edge[i].w=w;
    }
    int s,t;read(s),read(t);
    if(getv(s)!=getv(t)) return puts("IMPOSSIBLE"),0;
    sort(edge+1,edge+1+m,cmp);
    int ans1=-1,ans2=-1;
    for(re int l=1;l<=m;l++)
    {
        bool flag=0;
        int r;
        for(re int i=1;i<=n;i++) f[i]=i;
        for(re int i=l;i<=m;i++)
        {
            int u=edge[i].u,v=edge[i].v;
            int t1=getv(u),t2=getv(v);
            if(t1!=t2) f[t2]=t1;
            if(getv(s)==getv(t))
            {
                r=i;
                flag=1;
                break;
            }
        }
        if(flag)
        {
            if(ans1==-1&&ans2==-1) ans1=edge[r].w,ans2=edge[l].w;
            else if(ans1*edge[l].w>edge[r].w*ans2) ans1=edge[r].w,ans2=edge[l].w;
        }
    }
    int p=gcd(ans1,ans2);
    ans1/=p,ans2/=p;
    if(ans2==1) printf("%d
",ans1);
    else printf("%d/%d
",ans1,ans2);
    return 0;
}
原文地址:https://www.cnblogs.com/acm1ruoji/p/12008764.html