• CF-1354 E. Graph Coloring(二分图,背包,背包方案输出)


    E. Graph Coloring

    链接

    n个点m条边的无向图,不保证联通,给每个点标号1,2,3。1号点个数n1,2号点个数n2,3号点个数n3。且每条边的两点,标号之差绝对值为1。如果有合法方案,需输出方案。

    考虑每个联通子图,2只可以和1或者3连边,1只能和2连边,3只能和2连边,那么将1,3归为一堆,2归为一堆。每一堆内不存在边,构成一个独立点集,那么很明显是一个二分图,每次DFS可以找到二分图两部点的个数,如果存在奇环那么直接输出NO

    对于每个联通子图,一个二分图,假设左部有 x 个点,右部有y个点,那么可以给x个点标2号,或者给 y 个点标2号。问最后能否刚好凑够 n2 个2号点。这显然是一个背包问题。

    每个联通子图是一个物品,二分图两部分点的数量就是体积,可以记录路径也可以不记录。因为目标是凑够 n2 个点,那么如果第 i 个物品选择的不是二分图中标记为 2 的点,那么认为这个物品是反选的,也是将标记为 1 的点最终标记成了 2。

    对于1号点和3号点,在整个过程中都被标记成了1,所以只需要输出所有标记为1的点即可,如果n1个 1 全部输出,那么再紧接着输出 3即可。

    需要标记的东西:第 i 个物品的两个体积(左部点个数和右部点个数), 每个点的标号,每个点所属的物品编号,物品是否要反选(最后DP结束后倒推即可)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    #define dbg(x...) do { cout << "33[32;1m" << #x <<" -> "; err(x); } while (0)
    void err() { cout << "33[39;0m" << endl; }
    template<class T, class... Ts> void err(const T& arg,const Ts&... args) { cout << arg << " "; err(args...); }
    const int N = 5000 + 5;
    const int M = 200010;
    int head[N], ver[M], nxt[M], tot, cnt;
    int n, m, n1, n2, n3;
    int c[N], be[N], c1[N], c2[N], rev[N];
    int d[N][N];
    void add(int x, int y){
        ver[++tot] = y, nxt[tot] = head[x], head[x] = tot;
    }
    bool dfs(int x, int col){
        c[x] = col;
        be[x] = cnt;
        if(c[x] == 1) c1[cnt] ++;
        else c2[cnt] ++;
        for(int i=head[x];i;i=nxt[i]){
            int y = ver[i];
            if(!c[y]){
                if(!dfs(y, 3 - col)) return false;
            }
            if(c[y] + c[x] != 3) return false;
        }
        return true;
    }
    int main(){
        scanf("%d%d", &n,&m);
        scanf("%d%d%d", &n1, &n2, &n3);
        for(int i=1;i<=m;i++){
            int x, y;scanf("%d%d", &x, &y);
            add(x, y);add(y, x);
        }
        d[0][0] = 1;
        for(int i=1;i<=n;i++){
            if(c[i]) continue;
            cnt++;
            if(!dfs(i, 1)){
                puts("NO");
                return 0;
            }
            for(int j=c1[cnt];j<=n2;j++){
                d[cnt][j] |= d[cnt-1][j-c1[cnt]];
            }
            for(int j=c2[cnt];j<=n2;j++){
                d[cnt][j] |= d[cnt-1][j-c2[cnt]];
            }
        }
        if(!d[cnt][n2]) {
            puts("NO");return 0;
        }
        puts("YES");
        while(cnt){
            rev[cnt] = d[cnt-1][n2-c1[cnt]];
            if(rev[cnt]) n2 -= c1[cnt];
            else n2 -= c2[cnt];
            cnt --;
        }
        for(int i=1;i<=n;i++){
            if(rev[be[i]]) c[i] = 3 - c[i];
            if(c[i] == 2) putchar('2');
            else if(n1 > 0) putchar('1'), n1--;
            else putchar('3'); 
        }
    
        return 0;
    }
    
  • 相关阅读:
    已经完全付款的发票仍然可以选择并进行零金额的付款
    How to fix Safari can't download .DMG
    WPF学习笔记系列
    无废话WPF系列17:数据模版
    Mac 用GUI工具打开隐藏文件
    无废话WPF系列19:MVVM简单介绍
    ASP.NET MVC3实战系列(二):面向接口编程,提高系统可测试性。
    Windows文件被占用解决办法
    无废话WPF系列18:控件模版
    ASP.NET MVC3实战系列(三):MVC3中使用依赖注入(IOC)
  • 原文地址:https://www.cnblogs.com/1625--H/p/12907658.html
Copyright © 2020-2023  润新知