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;
}
posted @ 2024-06-19 21:53  chenfy27  阅读(1)  评论(0编辑  收藏  举报