Luogu P1525 关押罪犯

思路

这道题和同伙那道题差不多啊。都是利用并查集的补集来实现将敌人分开

这道题不一样的地方就是需要小小的贪个心。不难想到我们要使得怨恨值越大的两个罪犯尽量分开住,那么就按照边权从大到小进行排序。然后把敌人并到自己的补集中去。

知道有两个罪犯不得不被关在一起的时候。直接输出这条边的边权,结束程序。如果一直找不到的话,就证明没有纠纷发生,那就输出0

吐槽

警察局长应该要被开除了QwQ

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

const int maxnode = 2e4+3;
const int maxedge = 1e5+3;

using namespace std;

int f[maxnode], n, m, x, dig, enm[maxnode], xx, yy;
char c;
struct edge {
    int u, v, w;
}ed[maxedge];

inline int read() {
    x = 0, dig = 1;
    c = getchar();
    while (c < '0' || c > '9') {
        if(c == '-') dig = -1;
        c = getchar();
    }
    while (c <= '9' && c >= '0') {
        x = x*10 + c-'0';
        c = getchar();
    }
    return x * dig;
}

inline int find(int x) {
    return (f[x] == x) ? x : (f[x] = find(f[x]));
}

bool cmp(edge a, edge b) {
    return a.w > b.w;
}

int main() {
    n = read(), m = read();
    for(int i=1; i<=n; i++) {
        f[i] = i;
    }
    for(int i=1; i<=m; i++) {
        ed[i].u = read(), ed[i].v = read(), ed[i].w = read();
    }
    sort(ed+1, ed+1+m, cmp);
    for(int i=1; i<=m; i++) {
        if(find(ed[i].u) == find(ed[i].v)) {
            printf("%d", ed[i].w);
            return 0;
        }
        else {
            if(enm[ed[i].u] == 0) enm[ed[i].u] = ed[i].v;
            xx = find(ed[i].v), yy = find(enm[ed[i].u]);
            if(xx != yy) f[xx] = find(yy);
            if(enm[ed[i].v] == 0) enm[ed[i].v] = ed[i].u;
            xx = find(ed[i].u), yy = find(enm[ed[i].v]);
            if(xx != yy) f[xx] = find(yy);
        }
    }
    printf("0");
}

猜你喜欢

转载自www.cnblogs.com/bljfy/p/9316288.html
今日推荐