bzoj 1050 [HAOI2006]旅行comf (并查集)

题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1050

 

思路:

先将每条边的权值排个序优先小的,然后从小到大枚举每一条边,将其存到并查集里,如果得到的比值比之前的小,那么判断下s与t能否连通,如果连通就替换就好了

 

实现代码:

#include<bits/stdc++.h>
using namespace std;
const int M = 1e6+10;
int f[M],vis[M],a[M];
int n,m;
int Find(int x){
    if(x==f[x])return x;
    return f[x]=Find(f[x]);
}

void mix(int x,int y){
    int fx = Find(x);
    int fy = Find(y);
    if(fx != fy) f[fx] = fy;
}

bool cmp(int a,int b){
    return a > b;
}

struct node{
    int x,y,v;
    bool operator < (const node &cmp) const{
         return v < cmp.v;
    }
}e[M];

int main()
{
    int s,t;
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= m;i ++)
        scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].v);
    sort(e+1,e+1+m);
    scanf("%d%d",&s,&t);
    int minn = 1,maxx = 30000;
    for(int i = 1;i <= m;i ++){
        for(int j = 1;j <= n;j ++)  f[j] = j;
        for(int j = i;j <= m;j ++){
            mix(e[j].x,e[j].y);
            if(e[j].v*minn > e[i].v*maxx) break;
            if(Find(s) == Find(t)){
                int k = __gcd(e[j].v,e[i].v);
                minn = e[i].v/k; maxx = e[j].v/k;
               // cout<<k<<" "<<minn<<" "<<maxx<<endl;
                break;
            }
        }
    }
    if(maxx == 30000&&minn == 1) printf("IMPOSSIBLE\n");
    else if(minn == 1) printf("%d\n",maxx);
    else cout<<maxx<<"/"<<minn<<endl;
    return 0;
}

 

posted @ 2018-07-21 11:56  冥想选手  阅读(120)  评论(0编辑  收藏