码迷,mamicode.com
首页 > 其他好文 > 详细

Educational Codeforces Round 87 (Rated for Div. 2) E. Graph Coloring(dp)

时间:2020-05-19 00:23:20      阅读:60      评论:0      收藏:0      [点我收藏+]

标签:节点   out   方案   class   ++   init   com   sizeof   owa   

链接

题意

给定一张$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\n");
                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\n");
        return 0;
    }
    printf("YES\n");
    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)

标签:节点   out   方案   class   ++   init   com   sizeof   owa   

原文地址:https://www.cnblogs.com/aaddvvaanntteezz/p/12913900.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!