zoukankan      html  css  js  c++  java
  • codeforces 1244D Paint the Tree 题解

    updated 2019.11.10 之前笔误了

    首先这题的条件就在于 一棵树上任意两个距离(leq2)的点颜色不同 并且只有三种颜色

    那么如果存一个点(u) 有三个点与(u)相连 这三个点颜色就必须两两不同
    然后这三个点就把三种颜色取完了
    然后(u)就没办法取颜色了 这样就无解

    于是 只要存在任意一个节点的度数(geq3)就无解

    然后我们发现这棵树是条链

    再看这个链 任意三个相连的节点都需要两两颜色不同
    所以任意三个相连的节点只要确定了两个 第三个就确定了 就可以一步一步推下去了
    一开始就随便找一条边 与这条边相连的两个点分别枚举选什么颜色(这两个点颜色不能相同) 然后一步一步往外推 记录下六种情况下答案最小的情况 就可以了

    放个图吧 好理解

    确定过程(枚举(col1)(col2) 这里随便找一条边都行 我找了((4,5))这条边)
    J8nVRP.png
    下面是无解情况
    J8nmM8.png

    记录下每个点在这种情况下(枚举6种情况)标记成什么颜色 然后直接全部加起来 统计答案

    这是考场代码 我都是直接dfs的 其实不用 但反正复杂度对的 无所谓

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <cmath>
    using namespace std;
    typedef long long LL;
     
    LL n,m,k;
    LL c[4][800005] = {0};
    LL ans = 0;
    string s;
     
    LL ec = 0,to[800005],nxt[800005],hed[200005] = {0};
    LL deg[400005] = {0};
    void add_edge(LL f,LL t){
    	++ ec; to[ec] = t; nxt[ec] = hed[f]; hed[f] = ec;
    	deg[t] ++;
    }
     
    LL col[200005] = {0};
    LL rec[200005] = {0};
     
    LL chg(LL x,LL y){
    	return 6 - x - y; // 小技巧 根据另外两点颜色确定该点颜色
    }
     
    void dfs(LL u,LL f,LL uc,LL fc){ // 标记颜色
    	for(LL i = hed[u];i;i = nxt[i]){
    		LL v = to[i];
    		if(v == f) continue;
    		col[v] = chg(uc,fc);
    		dfs(v,u,col[v],uc);
    	}
    }
     
    int main(){
    	LL a,b;
    	ios::sync_with_stdio(false);
    	cin >> n;
    	for(LL i = 1;i <= n;i ++) cin >> c[1][i];
    	for(LL i = 1;i <= n;i ++) cin >> c[2][i];
    	for(LL i = 1;i <= n;i ++) cin >> c[3][i];
    	
    	for(LL i = 1;i < n;i ++){
    		cin >> a >> b;
    		add_edge(a,b);
    		add_edge(b,a);
    	}
    	
    	for(LL i = 1;i <= n;i ++){
    		if(deg[i] >= 3){
    			cout << -1 << endl;
    			return 0;
    		}
    	}
    	LL ans = 0x3f3f3f3f3f3f3f3f;
    	for(LL c1 = 1;c1 <= 3;c1 ++){
    		for(LL c2 = 1;c2 <= 3;c2 ++){
    			if(c1 == c2) continue;
    			col[a] = c1; col[b] = c2; // 随便找一条边 枚举
             // 我在这里直接用了最后输入的那条边
    			dfs(a,b,c1,c2);
    			dfs(b,a,c2,c1);
            // 注意要从两个点两个方向 都要dfs 
    			LL cnt = 0;
    			for(LL i = 1;i <= n;i ++) cnt += c[col[i]][i];
    			if(cnt < ans){
    				ans = cnt;
    				for(LL i = 1;i <= n;i ++) rec[i] = col[i]; // 记录答案
    			}
    		}
    	}
    	cout << ans << endl;
    	for(LL i = 1;i <= n;i ++) cout << rec[i] << (i == n ? '
    ' : ' '); 
    	return 0;
    }
    

    顺带一提 这场CF的D比C还简单

  • 相关阅读:
    软件测试的策略是什么?
    软件产品质量特性是什么?
    软件质量保证体系是什么 国家标准中与质量保证管理相关的几个标准是什么?他们的编号和全称是什么?
    简述什么是静态测试、动态测试、黑盒测试、白盒测试、α测试 β测试
    mac上的GNU gcc报错:dyld: Library not loaded: /usr/local/opt/isl/lib/libisl.22.dylib的解决办法
    两行信息量大的shell代码
    mac上的less使用扩展正则表达式比如
    设置mac默认使用GNU工具,比如使用GNU cat而不是BSD cat
    macos 10.15/Catalina 用不了gdb
    vscode的coderunner插件介绍
  • 原文地址:https://www.cnblogs.com/IltzInstallBI/p/12744235.html
Copyright © 2011-2022 走看看