Vijos1776关押罪犯

题目链接:https://vijos.org/p/1776

 这个题是老师讲并查集的时候拿来的例题,记得以前做的时候是二分+二分图染色,这次竟然是贪心+并查集,所以就实现了一下。

整体思路可以参考这里,假设关在一起的是朋友(虽然有怨气值,但毕竟是比较少的),那么对于思路的实现间代码:

#include<iostream>
#include<vector>
#include<algorithm>
#define MAXN 20010
#define MAXM 100010
using namespace std;

struct Edge
{
    int x, y;
    long long w;
    Edge(int x, int y, int w):x(x), y(y), w(w) {}
};
int f[MAXN];  //并查集数组
int d[MAXN];  //i的敌对罪犯
vector<Edge> edges;

int cmp(Edge a, Edge b)
{
    return a.w > b.w;
}

int Find(int x) //并查集压缩路径
{
    if (f[x] == x)
        return x;
    f[x] = Find(f[x]);
    return f[x];
}

int main()
{
    int n, m;

    cin>>n>>m;
    for (int i=1; i<=n; i++) f[i] = i;
    for (int i=0; i<m; i++)
    {
        int x, y, w;
        cin>>x>>y>>w;
        edges.push_back(Edge(x,y,w));
    }

    sort(edges.begin(), edges.end(), cmp);
    int ans = 0;
    for (int i=0; i<edges.size(); i++)
    {
        Edge e = edges[i];
        if (d[e.x] == 0) //如果e.x还没有敌对罪犯,就为设当前敌对罪犯
            d[e.x] = e.y;
        if (d[e.y] == 0) ///
            d[e.y] = e.x;
        int x = Find(e.x);
        int y = Find(e.y);
        int dx = Find(d[e.x]);
        int dy = Find(d[e.y]);
        if (x == y)  //如果是朋友,则矛盾,退出
        {
            ans = e.w;   //本来这里是直接输出答案然后return 0的,但是莫名其妙只有一个点儿wrong answer,径队友建议改成现在的样子就全过了,也不知道为什么
            break;
        }
        if (x != y) //不是朋友,则合并相应的朋友
        {
            f[Find(x)] = Find(f[dy]);
            f[Find(dx)] = Find(f[y]);
        }
    }
    cout<<ans<<endl;

    return 0;
}

你可能感兴趣的:(Vijos1776关押罪犯)