bzoj 1050: [HAOI2006]旅行comf 并查集

题目链接

1050: [HAOI2006]旅行comf

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2254  Solved: 1202
[Submit][Status][Discuss]

Description

给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000)。给你两个顶点S和T,求一条路径,使得路径上最大边和最小边的比值最小。如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个比值,如果需要,表示成一个既约分数。 备注: 两个顶点之间可能有多条路径。

Input

第一行包含两个正整数,N和M。 下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向公路,车辆必须以速度v在该公路上行驶。 最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比最小的路径。s和t不可能相同。

Output

如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。

Sample Input

【样例输入1】
4 2
1 2 1
3 4 2
1 4
【样例输入2】
3 3
1 2 10
1 2 5
2 3 8
1 3
【样例输入3】
3 2
1 2 2
2 3 4
1 3

Sample Output

【样例输出1】
IMPOSSIBLE
【样例输出2】
5/4
【样例输出3】
2
 
按边权大小排序, 然后开始枚举, i从1开始, 不停加边直到s和t联通, 设此时为r, 将并查集初始化, 从r开始反向枚举, 直到st联通, 这时为l, 那么[l, r]就是一个可能的解。 然后i变为l+1, 继续枚举。
 
我也不知道为什么这样对...
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <queue>
#include <stack>
#include <bitset>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, n, a) for(int i = a; i<n; i++)
#define fi first
#define se second
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int mod = 1e9+7;
const int inf = 1061109567;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
struct node
{
    int u, v, w;
    bool operator < (node a)const
    {
        return w<a.w;
    }
}a[5005];
int f[505], n;
void init() {
    for(int i = 1; i<=n; i++)
        f[i] = i;
}
int findd(int u) {
     return f[u] == u?u:f[u] = findd(f[u]);
}
int gcd(int a, int b) {
    return b?gcd(b, a%b):a;
}
int main()
{
    int m, s, t, maxx, minn;
    cin>>n>>m;
    for(int i = 0; i<m; i++) {
        scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].w);
    }
    cin>>s>>t;
    sort(a, a+m);
    double ans = inf;
    for(int i = 0, j; i<m; ) {
        init();
        int flag = 0;
        for(j = i; j<m; j++) {
            int u = findd(a[j].u);
            int v = findd(a[j].v);
            if(u != v) {
                f[u] = v;
            }
            if(findd(s) == findd(t)) {
                flag = 1;
                break;
            }
        }
        if(flag) {
            init();
            int k;
            for(k = j; ; k--) {
                int u = findd(a[k].u);
                int v = findd(a[k].v);
                if(u!=v)
                    f[u] = v;
                if(findd(s) == findd(t))
                    break;
            }
            if(ans>1.0*a[j].w/a[k].w) {
                maxx = a[j].w;
                minn = a[k].w;
                ans = 1.0*a[j].w/a[k].w;
            }
            i = k+1;
        } else {
            break;
        }
    }
    if(ans == inf) {
        puts("IMPOSSIBLE");
    } else {
        int x = gcd(maxx, minn);
        if(minn/x==1) {
            printf("%d
", maxx/x);
        } else {
            printf("%d/%d
", maxx/x, minn/x);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/yohaha/p/5230595.html