首页 > 其他分享 >lgP1525 关押罪犯

lgP1525 关押罪犯

时间:2024-06-19 22:00:24浏览次数:12  
标签:std return 关押 int auto edge -- 罪犯 lgP1525

给定N名罪犯和M组仇恨关系,第i组关系用a[i],b[i],w[i]标识,表示编号为a[i]与b[i]的罪犯之间的仇恨值为w[i]。现要将所有罪犯关押在两个房间里,使得同一房间内任意两名罪犯的最大仇恨值最小,求该最小值。

提示1:排查+种类并查集。类似最小生成树的做法,按仇恨值从大到小排序,按顺序枚举每个关系,如果双方已经在一起,则无法解决,当前仇恨值即为答案,否则将两人分开放。

#include <bits/stdc++.h>
using i64 = long long;

struct Edge {
    int x, y, w;  
};

struct DSU {
    std::vector<int> f;
    DSU(int n) {
        init(n);
    }
    void init(int n) {
        f.resize(n);
        std::iota(f.begin(), f.end(), 0);
    }
    int find(int x) {
        while (x != f[x]) {
            x = f[x] = f[f[x]];
        }
        return x;
    }
    void join(int x, int y) {
        x = find(x);
        y = find(y);
        if (x != y) {
            f[y] = x;
        }
    }
    bool same(int x, int y) {
        return find(x) == find(y);
    }
};

void solve() {
    int N, M;
    std::cin >> N >> M;
    std::vector<Edge> edge(M);
    for (int i = 0; i < M; i++) {
        std::cin >> edge[i].x >> edge[i].y >> edge[i].w;
        edge[i].x--;
        edge[i].y--;
    }
    std::sort(edge.begin(), edge.end(), [&](auto &u, auto &v){
        return u.w > v.w;
    });
    
    DSU dsu(2*N);
    for (auto &e : edge) {
        if (dsu.same(e.x, e.y)) {
            std::cout << e.w << "\n";
            return;
        }
        dsu.join(e.x, e.y+N);
        dsu.join(e.x+N, e.y);
    }
    std::cout << 0 << "\n";
}

int main() {
    std::cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    while (t--) solve();
    return 0;
}

提示2:二分+二分图。二分答案,假设当前答案为mid,将仇恨值大于mid的关系连边形成图,如果该图是二分图,则mid可行,否则不可行。

#include <bits/stdc++.h>
using i64 = long long;

struct Edge {
    int x, y, w;
};

bool isbp(int n, const std::vector<std::vector<int>> &adj) {
    std::vector<int> vis(n);
    auto dfs = [&](auto self, int x, int c) -> bool {
        vis[x] = c;
        for (auto i : adj[x]) {
            if (vis[i] == c) {
                return false;
            }
            if (vis[i] == 0 && !self(self, i, -c)) {
                return false;
            }
        }
        return true;
    };
    for (int i = 0; i < n; i++) {
        if (vis[i]) {
            continue;
        }
        if (dfs(dfs, i, 1) == 0) {
            return false;
        }
    }
    return true;
}

void solve() {
    int N, M;
    std::cin >> N >> M;
    std::vector<Edge> edge(M);
    for (int i = 0; i < M; i++) {
        std::cin >> edge[i].x >> edge[i].y >> edge[i].w;
        edge[i].x--;
        edge[i].y--;
    }
    std::sort(edge.begin(), edge.end(), [&](auto &u, auto &v){
        return u.w > v.w;
    });
    
    auto check = [&](int val) {
        std::vector<std::vector<int>> adj(N);
        for (auto &e : edge) {
            if (e.w <= val) {
                break;
            }
            adj[e.x].push_back(e.y);
            adj[e.y].push_back(e.x);
        }
        return isbp(N, adj);
    };
    
    int lo = 0, hi = 1e9, mid;
    while (lo < hi) {
        mid = (lo + hi) / 2;
        if (check(mid)) {
            hi = mid;
        } else {
            lo = mid + 1;
        }
    }
    std::cout << lo << "\n";
}

int main() {
    std::cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    while (t--) solve();
    return 0;
}

标签:std,return,关押,int,auto,edge,--,罪犯,lgP1525
From: https://www.cnblogs.com/chenfy27/p/18257519

相关文章

  • 关押罪犯
    S城现有两座监狱,一共关押着N名罪犯,编号分别为1~N。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多。如果两名怨气值为c的罪犯被......
  • P1525 [NOIP2010 提高组] 关押罪犯
    原题链接题解这题我采用了带权并查集的做法,0代表两囚犯处于监狱,1代表两囚犯不同监狱。根据题意,我们想让冲突值尽可能的小,那么我们要先把仇恨值大的两罪犯放在不同监狱;即按仇恨值从大到小的去判断每条仇恨信息。(贪心思想)code #include<bits/stdc++.h>usingnamespacestd;......
  • P1525 [NOIP2010 提高组] 关押罪犯
    带权并查集中,dist[]数组可以理解为一个向量,这样子比按照距离来理解更透彻:优秀学习资料:AcWing240.食物链(带权并查集)-AcWing即d[a]表示向量a->fa[a]这道题的并查集解法:#include<iostream>#include<stdio.h>#include<algorithm>#include<string>#include<cmath>......
  • 洛谷题单指南-集合-P1525 [NOIP2010 提高组] 关押罪犯
    原题链接:https://www.luogu.com.cn/problem/P1525题意解读:有很多罪犯,要关到两座监狱,有一些罪犯之间有仇,并且可以量化出仇恨值,如果关在一起就会冲突,造成的影响就是仇恨值,要使得造成的影响最小,如果可以完全不起冲突,输出0。解题思路:首先,要让冲突影响最小化,显然应该把仇恨大的罪犯......
  • P1525 [NOIP2010 提高组] 关押罪犯
    原题链接题解1:按边权从大到小排序,如果这条边的两个点没确定关系,那么把他们设为敌人这样,就成了一棵棵最大生成树(因为有的罪犯之间没有怨气)由敌人的敌人是朋友可以得出,如果两个点在同一棵树,且距离为偶数,那么代表他们之间互为朋友code1#include<bits/stdc++.h>usingnamespace......
  • 并查集基础 &打击罪犯
    并查集基础真的很基础题目描述:Description某个地区有n(n<=1000)个犯罪团伙,当地警方按照他们的危险程度由高到低给他们编号为1-n,他们有些团伙之间有直接联系,但是任意两个团伙都可以通过直接或间接的方式联系,这样这里就形成了一个庞大的犯罪集团,犯罪集团的危险程度唯一由集团内的......
  • [NOIP2010 提高组] 关押罪犯 - 洛谷
    P1525[NOIP2010提高组]关押罪犯-洛谷|计算机科学教育新生态(luogu.com.cn)种类并查集#include<bits/stdc++.h>#definedebug(a)cout<<#a<<"="<<a<<'\n';usingnamespacestd;usingi64=longlong;typedefpair<i64,i64>......
  • P1525 [NOIP2010 提高组] 关押罪犯
    P1525[NOIP2010提高组]关押罪犯法一:二分图把犯人分配到两个监狱,使得监狱内的怒气值最大最小分配到两个集合中,考虑二分染色分析因为答案具有单调性所以可以二分:判断x是否符合,只需要重建大于x的边,如果不能把它们分到两个集合中(二分染色失败),就往上调(考虑无限大,那么就不矛盾)......
  • UER#6 寻找罪犯
    以后推半天性质还是很模糊的话,也尝试尝试直接套算法。。算法导向!2-SAT!强行2-SAT的话,我们会有以下约束:若一个嫌疑人的供词中存在一个假话,他必然是犯人。若一个嫌疑人的供词中存在一个假话,其它话必然是真的。若一个嫌疑人不是犯人,他说的所有话一定都是真的。此时暴力连边......
  • 【NOIP2010】【codevs1069】关押罪犯(二分答案+二分图染色)
    problem将n个罪犯分别关押进2座监狱每2个罪犯之间有一个冲突值,当他们在同一监狱时就会爆发让爆发的冲突值(最大的那个)最小,求那个最小值solution考虑判定:是否存在一种分配方案......