CF1354E(20-10-15)

CF1354E

codeforce 1354E Graph Coloring

思想

  • 与2相邻的点都是1或3
  • 与1或3相邻的点都是2
  • 由黑白染色法可以先判断是否有解(必要条件)
  • 因为可能是非连通图,所以要用背包判断能不能凑出n2个点的独立集,如果凑不出也无解
  • 时间复杂度O(n2

代码

//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <algorithm>
#include <cmath>
#include <functional>
#define INF 0x3f3f3f3f
#define N 201010
#define M 1010
#define ll long long
using namespace std;
int edge,n,m,n1,n2,n3,top;
int to[N],nxt[N],wout[N],book[N],dp[5001][5001],color[N];
bool mk[N],flag;
vector <int> sum[N][2];
void add(int &s,int &e)
{
    to[++edge]=e;
    nxt[edge]=wout[s];
    wout[s]=edge;
}
void dfs(int x,int col)
{
    if(mk[x])
    {
        if(color[x]!=col) flag=false;
        return;
    }
    mk[x]=true;
    sum[top][col].push_back(x);
    color[x]=col;
    for(int i=wout[x];i;i=nxt[i])
    {
        dfs(to[i],col^1);
    }
}
int main()
{
    int a,b,k;
    flag=true;
	scanf("%d%d%d%d%d",&n,&m,&n1,&n2,&n3);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&a,&b);
        add(a,b);
        add(b,a);
    }
    for(int i=1;i<=n;i++)
        if(!mk[i])
        {
            ++top;
            dfs(i,1);
        }
    dp[0][0]=1;
    for(int i=1;i<=top;i++)
    {
        for(int j=n;j>=0;j--)
        {
            if(dp[i-1][j]) 
            {
                dp[i][j+sum[i][0].size()]=i*2;
                dp[i][j+sum[i][1].size()]=i*2+1;
            }
        }
    }
    if(!dp[top][n2]) flag=false;
    if(!flag)
    {
        printf("NO\n");
    }
    else
    {
        printf("YES\n");
        for(int i=n2;top;top--)
        {
            for(int j=0;j<sum[dp[top][i]/2][dp[top][i]%2].size();j++)
                book[sum[dp[top][i]/2][dp[top][i]%2][j]]=2;
            i-=sum[dp[top][i]/2][dp[top][i]%2].size();
        }
        for(int i=1;i<=n;i++)
            if(!book[i]) 
            {
                if(n1) n1--,book[i]=1;
                else book[i]=3;
            }
        for(int i=1;i<=n;i++)
            printf("%d",book[i]);
    }
	return 0;
}
/*

*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值