• hitachi2020 C-ThREE


    Link
    对图进行二分图染色(染为红蓝色),那么可以得到一个结论,所有距离为3的节点的颜色都必不相同。
    (R)为红色节点的个数,(B)为蓝色节点的个数,(X=lfloor frac N 3 floor)。(这里假设(Rleq B)
    将 1~n 分类为(1pmod 3,2pmod 3,0pmod3)这三类,则有以下两种情况。
    情况1:(Rleq X)
    此时可以将所有红节点分配得到(0pmod 3)的节点,这样每一个合法对((i,j))(即((i,j))的距离为3)都会有一个端点是3的倍数,它们的乘积必然是3的倍数。
    情况2:(R>X)
    此时将红节点分配得到(1pmod 3)的节点,将蓝节点分配得到(2pmod 3)的节点。剩下的(0pmod 3)的节点随意分配。
    这样每个合法对((i,j))的端点要么有3的倍数,要么其和为3的倍数。
    所以我们也证明了合法的排列分配方案是一定存在的。

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int N = 200010;
    
    int n;
    vector<int> G[N], v[2];
    int p[N];
    
    void dfs(int u, int fa, bool f) {
    	v[f].push_back(u);
    	for(auto &i : G[u]) if(i != fa) dfs(i, u, f ^ 1);
    } 
    
    int main() {
    	scanf("%d", &n);
    	for(int u, v, i = 1; i < n; ++i) {
    		scanf("%d%d", &u, &v);
    		G[v].push_back(u);
    		G[u].push_back(v);
    	}
    	dfs(1, 1, 1);
    	if(v[0].size() > v[1].size()) swap(v[0], v[1]);
    	int x = n / 3;
    	if((int)v[0].size() <= x) {
    		int now = 3, T = 0;
    		for(auto &i : v[0]) p[i] = now, now += 3;
    		for(auto &i : v[1]) {
    			if(now > n) now = ++T;
    			p[i] = now;
    			now += 3;
    		}
    	} else {
    		int now = 1;
    		for(auto &i : v[0]) {
    			p[i] = now;
    			now += 3;
    			if(now > n) now = 3;
    		}
    		int T = now;
    		now = 2;
    		for(auto &i : v[1]) {
    			p[i] = now;
    			now += 3;
    			if(now > n) now = T;
    		}
    	}
    	for(int i = 1; i <= n; ++i) printf("%d ", p[i]);
    	return 0;
    }
    
  • 相关阅读:
    C语言与内存模型初探
    【编辑中】软件工程知识萃取
    【深入理解计算机系统01】不同层级程序指令间的转换
    【统计学中的普适智慧】假设检验
    windows 内部预览版与迅雷极速版不配合
    网络安全理论初涉
    Unix philosophy
    BOP 2016 复赛题目
    10.8做题——USACO1.2命名那个数字(Name That Number)
    10.6上课——problem1切割木板(USACO 2006 November Gold)
  • 原文地址:https://www.cnblogs.com/henry-1202/p/12635306.html
Copyright © 2020-2023  润新知