Educational Codeforces Round 87 (Rated for Div. 2) E. Graph Coloring(dp)
Posted aaddvvaanntteezz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 87 (Rated for Div. 2) E. Graph Coloring(dp)相关的知识,希望对你有一定的参考价值。
题意
给定一张$n$个点,$m$条边的无向图,要求给每个点标为1,2,3中的一个值,使任意一条边上的两个点差的绝对值为1,并且标号为1,2,3的点分别有$n1,n2,n3$个,求一种方案题解
- 显然如果存在一组解,那么此图的每一个连通块一定是一个二分图。
- $dfs$求出所有的连通块,每一个连通块标号为1,3的点一定在同一侧,因为1,3之间不能连边。
- 所以给每一个连通块染色,计算出左部和右部节点的数量$c0$和$c1$,然后就可以$dp$了
- $dp_{i,j}$表示前$i$个连通块有$j$个点标为2是否可行。
- 转移:$dp_{i,j}=dp_{i-1,j-c0}|dp_{i-1,j-c1}$
- 因为要输出方案所以可以用记忆化搜索记录方案
查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5000+5;
const int maxm = 100005;
const int mod = 1e9+7;
ll qpow(ll a,ll b){ll res=1;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
struct graph
{
int head[maxm],nxt[maxm<<1],to[maxm<<1],w[maxm<<1],sz;
void init(){memset(head,-1,sizeof(head));}
graph(){init();}
void push(int a,int b,int c){nxt[sz]=head[a],to[sz]=b,w[sz]=c,head[a]=sz++;}
int& operator[](const int a){return to[a];}
}g;
bool vis[maxn],color[maxn];
int dp[maxn][maxn];
vector<int>belong[maxn];
int num;
int ans[maxn];
void dfs(int now)
{
vis[now]=1;
belong[num].push_back(now);
for(int i = g.head[now];~i;i = g.nxt[i]){
if(vis[g[i]]){
if(color[g[i]]==color[now]){
printf("NO
");
exit(0);
}
continue;
}
color[g[i]]=!color[now];
dfs(g[i]);
}
}
bool solve(int now,int res)
{
if(res<0)return 0;
if(dp[now][res]!=-1)return dp[now][res];
if(now==num+1&&res==0)return 1;
else if(now==num+1)return 0;
int c1,c0;
c1=c0=0;
for(auto i:belong[now]){
if(color[i]==0)c0++;
else c1++;
}
if(solve(now+1,res-c0)){
for(auto i:belong[now]){
if(color[i])ans[i]=1;
else ans[i]=2;
}
dp[now][res]=1;
return true;
}
else if(solve(now+1,res-c1)){
for(auto i:belong[now]){
if(color[i])ans[i]=2;
else ans[i]=1;
}
dp[now][res]=1;
return true;
}
dp[now][res]=0;
return false;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("simple.in", "r", stdin);
freopen("simple.out", "w", stdout);
#endif
int n,m,a,b,c;
memset(dp,-1,sizeof(dp));
cin>>n>>m>>a>>b>>c;
for(int i = 1,a,b;i <= m;++i){
scanf("%d%d",&a,&b);
g.push(a,b,0);
g.push(b,a,0);
}
for(int i = 1;i <= n;++i){
if(!vis[i]){
num++;
dfs(i);
}
}
int nowa=0;
if(!solve(1,b)){
printf("NO
");
return 0;
}
printf("YES
");
for(int i = 1;i <= n;++i){
if(ans[i]==1&&nowa<a){
nowa++;
printf("1");
}
else if(ans[i]==1)printf("3");
else printf("2");
}
return 0;
}
以上是关于Educational Codeforces Round 87 (Rated for Div. 2) E. Graph Coloring(dp)的主要内容,如果未能解决你的问题,请参考以下文章
Educational Codeforces Round 7 A
Educational Codeforces Round 7
Educational Codeforces Round 90
Educational Codeforces Round 33