关押罪犯

P1525 [NOIP2010 提高组] 关押罪犯 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

  • 额外用一个flag数组,flag[i]=j代表与i冲突最大的一个人
  • 生成树的时候权值大的排前面
  • 如果当前两个点没有并起来,那么看它们是否都已经有了冲突最大的敌人,(因为权值大的排前面,所以第一点是直接满足的),如果有那就把x与y冲突最大的合并,y与x冲突最大的合并,只有这样才能让冲突尽量减小
  • 如果当前两点是同一个祖先,那么说明它们之间肯定在这之前通过其他边相连起来了,而由于权值大的排前面,所以为了减小冲突,就可以连这两条边,这种连法肯定比它们祖先之间的某种连法冲突小,由于只要求最大的冲突,那么直接输出就好,至于其他的冲突量肯定比这个小,直接不考虑就行
// https://www.luogu.com.cn/problem/P1525
#include <bits/stdc++.h>
using namespace std;
#define MAX 10000001
int n, m, parent[MAX], flag[MAX];
struct Node
{
    int x, y, w;
} edge[MAX];
int fa(int x)
{
    return x == parent[x] ? x : parent[x] = fa(parent[x]);
}
void work()
{
    for (int i = 1; i <= m + 1; i++)
    {
        int x = edge[i].x, y = edge[i].y, fx = fa(x), fy = fa(y);
        if (fx == fy)
        {
            printf("%d", edge[i].w);
            exit(0);
        }
        if (flag[x] == 0)
            flag[x] = y;
        else
            parent[fa(flag[x])] = fy;
        if (flag[y] == 0)
            flag[y] = x;
        else
            parent[fa(flag[y])] = fx;
    }
}
bool cmp(Node a, Node b)
{
    return a.w > b.w;
}
void init()
{
    for (int i = 1; i <= n; i++)
        parent[i] = i;
}
void input()
{
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        edge[i] = (Node){a, b, c};
    }
    sort(edge + 1, edge + 1 + m, cmp);
}
int main()
{
    input();
    init();
    work();
}

 

posted on 2022-08-09 11:29  樵风  阅读(36)  评论(0)    收藏  举报