zoukankan      html  css  js  c++  java
  • 4.3 每日一题题解

    关押罪犯

    涉及知识点:

    • 并查集+贪心 / 二分图+二分

    solution:

    • 本题解法不唯一
    • 首先先讲一下并查集+贪心的做法:
    • 题意要求答案最小,所以仇恨值偏大的一对可以视为敌人分开,所以先根据仇恨值sort
    • 根据敌人的敌人就是友人,假如我们将a和b分开,b和c分开,那a和c就相当于在同一个监狱里,b在另外一个监狱里
    • 所以通过并查集,开大一倍数组,用来维护罪犯的补集,即不在同一个监狱的罪犯集合
    • 下面讲一下二分 + 二分图(需要有二分图的前提知识):
    • 很明显答案是要求最大值最小,所以二分答案
    • 然后根据染色法判断二分图是否成立,以及边权的最大值是否小于等于当前的二分答案

    并查集+贪心 std:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int maxn = 200005;
    int f[maxn];
    struct node{
        int u,v,w;
    }a[maxn*10];
    bool cmp(node p1,node p2){
        return p1.w > p2.w;
    }
    int find(int x){
        return f[x] == x ? f[x] : f[x] = find(f[x]);
    }
    void unite(int x,int y){
        x = find(x),y = find(y);
        if(x != y)
            f[x] = y;
    }
    int main()
    {
        int n,m;
        cin>>n>>m;
        for(int i=1;i<=2*n;i++)f[i] = i;
        for(int i=1;i<=m;i++)cin>>a[i].u>>a[i].v>>a[i].w;
        sort(a+1,a+1+m,cmp);
        for(int i=1;i<=m;i++)
        {
            int x = a[i].u;
            int y = a[i].v;
            x = find(x),y = find(y);
            if(x == y){
                cout<<a[i].w<<endl;
                return 0;
            }
            f[x] = find(n + a[i].v);
            f[y] = find(n + a[i].u);
        }
        cout<<"0"<<endl;
        return 0;
    }
    

    二分 + 二分图 std(感谢清楚姐的小迷弟贡献的代码):

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
     
    using namespace std;
     
    const int N = 20010, M = 200010;
     
    int n, m;
    int h[N], e[M], w[M], ne[M], idx;
    int color[N];
     
    void add(int a, int b, int c)
    {
        e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
    }
     
    bool dfs(int u, int c, int mid)
    {
        color[u] = c;
        for (int i = h[u]; ~i; i = ne[i])
        {
            int j = e[i];
            if (w[i] <= mid) continue;
            if (color[j])
            {
                if (color[j] == c) return false;
            }
            else if (!dfs(j, 3 - c, mid)) return false;
        }
     
        return true;
    }
     
    bool check(int mid)
    {
        memset(color, 0, sizeof color);
        for (int i = 1; i <= n; i ++ )
            if (!color[i])
                if (!dfs(i, 1, mid))
                    return false;
        return true;
    }
     
    int main()
    {
        scanf("%d%d", &n, &m);
        memset(h, -1, sizeof h);
     
        while (m -- )
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            add(a, b, c), add(b, a, c);
        }
     
        int l = 0, r = 1e9;
        while (l < r)
        {
            int mid = l + r >> 1;
            if (check(mid)) r = mid;
            else l = mid + 1;
        }
     
        printf("%d
    ", r);
     
        return 0;
    }
    
  • 相关阅读:
    python 获取当前路径
    python 执行结果输出为txt
    python def 定义函数
    python:浅析python 中__name__ = ‘__main__’ 的作用
    python 数组新增或删除元素
    python在Windows安装PIL的方法
    静态路由学习总结
    zookeeper客户端命令行操作
    kudu安装过程中可能出现的问题
    sudo: /etc/sudoers is world writable|给用户添加权限报错
  • 原文地址:https://www.cnblogs.com/QFNU-ACM/p/12624763.html
Copyright © 2011-2022 走看看