• 2019 ICPC 陕西西安邀请赛 D. Miku and Generals


    传送门:https://nanti.jisuanke.com/t/39271

    题意:

    给你n个人,每个人有一个权值 a_i ​,(a_i​是可以被100整除的))现在需要你将n个人分成两组,有m个关系,a和b有关系代表a和b不能放在同一个组内,为了两组实力尽量平均,要你求两组权值差值最小时最大的值是哪一个

    题解:

    二分图染色+dp

    首先我们知道n个人必须全选分为两组,其次题目保证有解

    因此我们很容易想到如果a->b,b->c,那么a一定和c要分在同一组内

    这样我们就得到了很多个联通块

    错误想法:我们得到了num个联通块后直接将num个联通块做01背包就可以求出差值最小时最大值,dp状态定义为前i个物品,容量为j时的最大值,但是实际上这样有可能把错误的情况考虑进来,例如两个矛盾的块同时放进一个背包,例如这组数据

    2
    4 1
    300 300 100 500
    1 2
    6 4
    1000 2000 1000 1500 1000 1500
    1 2
    2 3
    4 5
    5 6

    01背包得到的答案是600 和 4000,实际上应该是 800和5000

    正确想法,我们将物品分成联通块后,对分成的两个联通块做差值,之后枚举差值能否达到才是最优解,为了防止差值为负,我们在中间加上一个比较大的数即可

    代码:

    错误写法:

    #include <set>
    #include <map>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <ctime>
    #include <bitset>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    typedef long long LL;
    typedef long long ll;
    typedef pair<LL, LL> pLL;
    typedef pair<LL, int> pLi;
    typedef pair<int, LL> pil;;
    typedef pair<int, int> pii;
    typedef unsigned long long uLL;
    #define ls rt<<1
    #define rs rt<<1|1
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    #define bug printf("*********
    ")
    #define FIN freopen("input.txt","r",stdin);
    #define FON freopen("output.txt","w+",stdout);
    #define IO ios::sync_with_stdio(false),cin.tie(0)
    #define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]
    "
    #define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]
    "
    #define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]
    "
    
    const double eps = 1e-8;
    const int mod = 1e9 + 7;
    const int maxn = 2e5 + 5;
    const int INF = 0x3f3f3f3f;
    const LL INFLL = 0x3f3f3f3f3f3f3f3f;
    struct EDGE {
        int v, nxt;
    } edge[maxn << 1];
    int head[maxn], tot;
    void add_edge(int u, int v) {
        edge[tot].v = v;
        edge[tot].nxt = head[u];
        head[u] = tot++;
    }
    int a[maxn];
    int num[maxn];
    int num1, num2;
    int vis[maxn];
    int dp[205][maxn];
    void dfs(int u, int flag) {
        vis[u] = 1;
        if(flag) num1 += a[u];
        else num2 += a[u];
        for(int i = head[u]; i != -1; i = edge[i].nxt) {
            int v = edge[i].v;
            if(vis[v]) continue;
            dfs(v, !flag);
        }
    }
    int main() {
    #ifndef ONLINE_JUDGE
        FIN
    #endif
        int T;
        scanf("%d", &T);
        while(T--) {
            int n, m;
            memset(head, -1, sizeof(head));
            tot = 0;
            int cur = 0;
            int sum = 0, ret;
            memset(vis, 0, sizeof(vis));
            memset(num, 0, sizeof(num));
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= n; i++) {
                scanf("%d", &a[i]);
                a[i] /= 100;
                sum += a[i];
            }
            ret = sum / 2;
            for(int i = 1, u, v; i <= m; i++) {
                scanf("%d%d", &u, &v);
                add_edge(u, v);
                add_edge(v, u);
            }
            for(int i = 1; i <= n; i++) {
                if(!vis[i]) {
                    num1 = 0, num2 = 0;
                    dfs(i, 0);
                    if(num1 != 0) {
                        num[++cur] = num1;
                    }
                    if(num2 != 0) {
                        num[++cur] = num2;
                    }
                }
            }
            memset(dp, 0, sizeof(dp));
            for(int i = 1; i <= cur; i++) {
                for(int j = 0; j <= ret; j++) {
                    dp[i][j] = dp[i - 1][j];
                    if(j >= num[i])dp[i][j] = max(dp[i][j], dp[i - 1][j - num[i]] + num[i]);
                }
            }
    
            printf("%d
    ", (sum - dp[cur][ret]) * 100);
    
        }
        return 0;
    }
    

    正确写法:

    #include <set>
    #include <map>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <ctime>
    #include <bitset>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    typedef long long LL;
    typedef long long ll;
    typedef pair<LL, LL> pLL;
    typedef pair<LL, int> pLi;
    typedef pair<int, LL> pil;;
    typedef pair<int, int> pii;
    typedef unsigned long long uLL;
    #define ls rt<<1
    #define rs rt<<1|1
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    #define bug printf("*********
    ")
    #define FIN freopen("input.txt","r",stdin);
    #define FON freopen("output.txt","w+",stdout);
    #define IO ios::sync_with_stdio(false),cin.tie(0)
    #define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]
    "
    #define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]
    "
    #define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]
    "
    
    const double eps = 1e-8;
    const int mod = 1e9 + 7;
    const int maxn = 2e5 + 5;
    const int INF = 0x3f3f3f3f;
    const LL INFLL = 0x3f3f3f3f3f3f3f3f;
    struct EDGE {
        int v, nxt;
    } edge[maxn << 1];
    int head[maxn], tot;
    void add_edge(int u, int v) {
        edge[tot].v = v;
        edge[tot].nxt = head[u];
        head[u] = tot++;
    }
    int a[maxn];
    int num[maxn];
    int num1, num2;
    int vis[maxn];
    int dp[205][maxn];
    void dfs(int u, int flag) {
        vis[u] = 1;
        if(flag) num1 += a[u];
        else num2 += a[u];
        for(int i = head[u]; i != -1; i = edge[i].nxt) {
            int v = edge[i].v;
            if(vis[v]) continue;
            dfs(v, !flag);
        }
    }
    int main() {
    #ifndef ONLINE_JUDGE
        FIN
    #endif
        int T;
        scanf("%d", &T);
        while(T--) {
            int n, m;
            memset(head, -1, sizeof(head));
            tot = 0;
            int cur = 0;
            int sum = 0, ret;
            memset(vis, 0, sizeof(vis));
            memset(num, 0, sizeof(num));
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= n; i++) {
                scanf("%d", &a[i]);
                a[i] /= 100;
                sum += a[i];
            }
    
            for(int i = 1, u, v; i <= m; i++) {
                scanf("%d%d", &u, &v);
                add_edge(u, v);
                add_edge(v, u);
            }
            ret = 0;
            for(int i = 1; i <= n; i++) {
                if(!vis[i]) {
                    num1 = 0, num2 = 0;
                    dfs(i, 0);
                    num[++cur] += abs (num1 - num2);
                    ret += abs(num1 - num2);
                }
            }
            memset(dp, 0, sizeof(dp));
            dp[0][100000] = 1;
            for (int i = 1; i <= cur; i++) {
                for (int j = -ret; j <= ret; j++) {
                    if (dp[i - 1][j - num[i] + 100000]) dp[i][j + 100000] = 1;
                    if (dp[i - 1][j + num[i] + 100000]) dp[i][j + 100000] = 1;
                }
            }
            for (int i = 100000; i <= 100000 + ret; i++) {
                if (dp[cur][i]) {
                    int x = i - 100000;
                    printf("%d
    ", 100 * ((sum - x) / 2 + x));
                    break;
                }
            }
    
        }
        return 0;
    }
    
    每一个不曾刷题的日子 都是对生命的辜负 从弱小到强大,需要一段时间的沉淀,就是现在了 ~buerdepepeqi
  • 相关阅读:
    或许因为缺少默认route配置而导致的的ping超慢,甚至timeout
    zabbix没有frontends目录
    jenkins自动部署到tomcat报错:ERROR: Publisher hudson.plugins.deploy.DeployPublisher aborted due to exception
    tomcat访问manager报404;server.xml中配置了Context path
    配置使用;yum安装slatstack的master,minion<at>centos6_x86_64
    jenkins报错;自定义工作目录;
    深入剖析Java中的装箱和拆箱
    探秘Java中的String、StringBuilder以及StringBuffer
    Java异常处理和设计
    JVM的内存区域划分
  • 原文地址:https://www.cnblogs.com/buerdepepeqi/p/10931360.html
Copyright © 2020-2023  润新知