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 << "\033[32;1m" << #x <<" -> "; err(x); } while (0)
void err() { cout << "\033[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;
}

CF-1354 E. Graph Coloring(二分图,背包,背包方案输出)的更多相关文章

  1. Codeforces 664D Graph Coloring 二分图染色

    题意: 一个无向图的每条边为红色或蓝色,有这样一种操作:每次选一个点,使与其相邻的所有边的颜色翻转. 求解是否可以经过一系列操作使所有的边颜色相同,并输出最少操作次数和相应的点. 分析: 每个点要么选 ...

  2. luogu P2066 机器分配[背包dp+方案输出]

    题目背景 无 题目描述 总公司拥有高效设备M台,准备分给下属的N个分公司.各分公司若获得这些设备,可以为国家提供一定的盈利.问:如何分配这M台设备才能使国家得到的盈利最大?求出最大盈利值.其中M≤15 ...

  3. [多校联考2019(Round 5 T2)]蓝精灵的请求(二分图染色+背包)

    [多校联考2019(Round 5)]蓝精灵的请求(二分图染色+背包) 题面 在山的那边海的那边住着 n 个蓝精灵,这 n 个蓝精灵之间有 m 对好友关系,现在蓝精灵们想要玩一个团队竞技游戏,需要分为 ...

  4. poj 1419 Graph Coloring

    http://poj.org/problem?id=1419 题意: 一张图黑白染色,相邻点不能都染黑色,最多能染几个黑色点 最大点独立集 但是图不能同构为二分图,不能用二分图匹配来做 那就爆搜吧 还 ...

  5. 【POJ】1419:Graph Coloring【普通图最大点独立集】【最大团】

    Graph Coloring Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5775   Accepted: 2678   ...

  6. POJ 1419 Graph Coloring(最大独立集/补图的最大团)

    Graph Coloring Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4893   Accepted: 2271   ...

  7. POJ1419 Graph Coloring(最大独立集)(最大团)

                                                               Graph Coloring Time Limit: 1000MS   Memor ...

  8. uva193 - Graph Coloring

    Graph Coloring You are to write a program that tries to find an optimal coloring for a given graph. ...

  9. UVA Graph Coloring

    主题如以下: Graph Coloring  You are to write a program that tries to find an optimal coloring for agiven ...

随机推荐

  1. 性能超四倍的高性能.NET二进制序列化库

    二进制序列化在.NET中有很多使用场景,如我们使用分布式缓存时,通常将缓存对象序列化为二进制数据进行缓存,在ASP.NET中,很多中间件(如认证等)也都是用了二进制序列化. 在.NET中我们通常使用S ...

  2. 【递归】P2386放苹果

    题目相关 题目描述 把 m个同样的苹果放在 n个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法.(5,1,1 和 1,1,5 是同一种方法) 输入格式 第一行是测试数据的数目 t,以下每行 ...

  3. NOIP初赛篇——06数制转换

    进位计数制的基本概念 ​ 将数字符号按顺序排列成数位,并遵照某种由低到高的进位方式计数表示数值的方法,称作为计数制. 十进制 十进制计数制由0.1.2.3.4.5.6.7.8.9共10个数字符号组成. ...

  4. PHP 插件资源

    PHP   jsonRPC  百度云网盘地址  https://pan.baidu.com/s/1itCIhrdd5bPGJMefNUuKvw   提取码 : ax4d PHP Excel 百度云网盘 ...

  5. 【Git】命令行操作

    Git 命令行操作 1 本地库初始化 git init:初始化本地仓库 效果 注意:.git目录中存放的是本地库相关的子目录和文件,不要删除,也不要胡乱修改. 2 设置签名 形式: 用户名:tom E ...

  6. 剑指offer 面试题9:用两个栈实现队列

    题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 使用栈实现队列的下列操作:push(x) -- 将一个元素放入队列的尾部.pop() -- 从队列首部移 ...

  7. Session、Cookie与Token

    http协议是无状态协议 协议是指计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则,超文本传输协议(HTTP)是一种通信协议,它允许将超文本标记语言(HTML)文档从Web服务器传送到 ...

  8. 通过trace分析优化其如何选择执行计划

    mysql5.6提供了对sql的跟踪trace,通过trace文件能够进一步了解为什么优化其选择执行计划a而不选b执行计划,帮助我们更好的理解优化其的行为. 使用方式:首先打开trace,设置格式为j ...

  9. C++导言与入门

    写在开始 计算机编程语言: Remember that a program is just a sequence of instructions telling a computer what to ...

  10. yml文件中${DB_HOST:localhost}的含义

    引自:https://blog.csdn.net/chen462488588/article/details/109057342 今天学习eladmin项目中看到application-dev.yml ...