• E. Graph Coloring dp+图论 or 思维


    E. Graph Coloring dp+图论 or 思维

    涂色的三个要求:
    1 每一个节点只能涂成 1 2 3 这三种颜色中的一种
    2 涂成颜色1的节点数量必须是n1
    3 涂成颜色2的节点数量必须是n2
    4 涂成颜色3的节点数量必须是n3
    5 如果(u,v)连边,那么u和v的颜色的差值必须等于1

    从上面可以得到:
    如果我定节点u的颜色是 1或者3,那么和它连的边的颜色都是2
    如果定节点u的颜色是2,那么和它连的边的颜色是1或者3
    这个1或者3都是没有限制的,因为1相连的边必须是2和3是等价的
    因为2的节点一定是可以定量求出来的,因为每隔一个节点就必须是2
    但是如果存在环的大小是一个奇数,那么一定没有结果。
    如果环的大小都是偶数,那么可以求出2的数量,
    因为这个2一定是每隔一个节点就一定是2,所以说1和3可以随意分配

    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f
    using namespace std;
    const int maxn = 2e5+10;
    typedef long long ll;
    /***
    涂色的三个要求:
    1 每一个节点只能涂成 1 2 3 这三种颜色中的一种
    2 涂成颜色1的节点数量必须是n1
    3 涂成颜色2的节点数量必须是n2
    4 涂成颜色3的节点数量必须是n3
    5 如果(u,v)连边,那么u和v的颜色的差值必须等于1
    
    从上面可以得到:
    如果我定节点u的颜色是 1或者3,那么和它连的边的颜色都是2
    如果定节点u的颜色是2,那么和它连的边的颜色是1或者3
    这个1或者3都是没有限制的,因为1相连的边必须是2和3是等价的
    因为2的节点一定是可以定量求出来的,因为每隔一个节点就必须是2
    但是如果存在环的大小是一个奇数,那么一定没有结果。
    如果环的大小都是偶数,那么可以求出2的数量,
    因为这个2一定是每隔一个节点就一定是2,所以说1和3可以随意分配
    ***/
    
    int n,m;
    int n1,n2,n3;
    int head[maxn],to[maxn<<1],nxt[maxn<<1],cnt;
    void add(int u,int v){
    	++cnt,to[cnt]=v,nxt[cnt]=head[u],head[u]=cnt;
    	++cnt,to[cnt]=u,nxt[cnt]=head[v],head[v]=cnt;
    }
    bool flag = false;
    int sum[maxn],num[maxn];
    int dep[maxn],fa[maxn],vis[maxn],now = 0,v[maxn],f[maxn];
    void dfs(int u,int pre,int d){
    	if(flag) return ;
    	if(d&1) vis[u] = 1,num[now]++;
    	else vis[u] = 0;
    	// printf("u=%d pre=%d d=%d
    ", u,pre,d);
    	v[u] = now,sum[now]++;
    	dep[u] = d,fa[u] = pre;
    	for(int i=head[u];i;i=nxt[i]){
    		int v = to[i];
    		if(v==pre) continue;
    		if(!dep[v]) dfs(v,u,d+1);
    		else{
    			if(flag) return ;
    			int len = dep[u]-dep[v]+1;
    			if(len&1){flag = true;return ;}
    		}
    	}
    }
    
    bool dp[5005][5005];
    int main(){
    	scanf("%d%d",&n,&m);
    	scanf("%d%d%d",&n1,&n2,&n3);
    	for(int i=1;i<=m;i++) {
    		int u,v;
    		scanf("%d%d",&u,&v);
    		add(u,v);
    	}
    	now = 0;
    	flag = false;
    	for(int i=1;i<=n;i++){
    		if(!dep[i]) {
    			++now;
    			// printf("i=%d
    ", i);
    			dfs(i,0,1);
    			if(flag) break;	
    		}
    	}
    	if(flag) printf("NO
    ");
    	else{
    		memset(dp,false,sizeof(dp));
    		dp[0][0] = true;
    		for(int i=1;i<=now;i++){
    			for(int j=0;j<=n2;j++){
    				if(j>=num[i]&&dp[i-1][j-num[i]]) dp[i][j] = true;
    				else if(j+num[i]-sum[i]>=0&&dp[i-1][j+num[i]-sum[i]]) dp[i][j] = true;
    			}
    		}
    		if(!dp[now][n2]) printf("NO
    ");
    		else{
    			int cur = n2;
    			for(int i=now;i>=1;i--){
    				if(cur>=num[i]&&dp[i-1][cur-num[i]]) f[i] = 1,cur = cur-num[i];
    				else f[i] = 0,cur = cur + num[i] - sum[i];
    			}
    			printf("YES
    ");
    			for(int i=1;i<=n;i++){
    				if(vis[i]==f[v[i]]) printf("2");
    				else {
    					if(n1) printf("1"),n1--;
    					else printf("3");
    				}
    			}
    			printf("
    ");
    		}
    	}
    
    }
    
  • 相关阅读:
    最全Pycharm教程
    Django系列:(1)PyCharm下创建并运行我们的第一个Django工程
    用pycharm+django开发web项目
    python在不同层级目录import模块的方法
    Android GetTimeAgo(时间戳转换几天前,几分钟前,刚刚等)
    Fresco简单的使用—SimpleDraweeView
    django常用命令
    Android 浅谈 RxAndroid + Retrofit + Databinding
    云计算之路-阿里云上:负载均衡从七层换成四层后的意外发现团队
    云计算之路-阿里云上:因为网络问题,物理机换回虚拟机团队
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/13635263.html
Copyright © 2020-2023  润新知