zoukankan      html  css  js  c++  java
  • CF830E Perpetual Motion Machine

    题面

    题解

    神仙构造题。

    分五种情况考虑:

    • 如果存在一个环,那么令环上的点权值为(1),其余点权值为(0)
    • 如果存在一个度数大于(3)的点,令这个点的权值为(2),和它相邻的点权值为(1),否则权值为(0)
    • 如果存在两个度数等于(3)的点,令这两个点的路径上点的权值为(2),其余的点权值为(1)
    • 如果只有一个点度数为(3),那么这张图一定是这个点伸出三条链,设三条链的长度分别为(l_1, l_2, l_3),那么有解当且仅当(frac 1{l_1 + 1} + frac 1{l_2 + 1} + frac 1{l_3 + 1} leq 1)
    • 如果没有点度数为(3),可以证明一定无解。

    于是就可以按照结论欢乐构造了。

    代码

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
    
    inline int read()
    {
    	int data = 0, w = 1; char ch = getchar();
    	while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    	if (ch == '-') w = -1, ch = getchar();
    	while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
    	return data * w;
    }
    
    const int maxn(1e5 + 10);
    struct edge { int next, to; } e[maxn << 1];
    int head[maxn], e_num, n, m, vis[maxn], d[maxn], deg[maxn];
    std::vector<int> vec[3];
    inline void add_edge(int from, int to)
    {
    	e[++e_num] = (edge) {head[from], to};
    	head[from] = e_num, ++deg[to];
    }
    
    void Set(int x)
    {
    	vis[x] = 0; if (!d[x]) d[x] = 1;
    	for (int i = head[x]; i; i = e[i].next)
    		if (vis[e[i].to]) Set(e[i].to);
    }
    
    int findCir(int x, int f)
    {
    	vis[x] = 1;
    	for (int i = head[x]; i; i = e[i].next)
    		if (!vis[e[i].to]) { if (findCir(e[i].to, x)) return 1; }
    		else if (e[i].to != f) return 1;
    	return 0;
    }
    
    int findDeg(int x, int f)
    {
    	if (f && deg[x] == 3) return d[x] = 2, 1;
    	for (int i = head[x]; i; i = e[i].next)
    		if (e[i].to != f) if (findDeg(e[i].to, x)) { d[x] = 2; return 1; }
    	return 0;
    }
    
    void dfs(int x, int f, std::vector<int> &v)
    {
    	v.push_back(x);
    	for (int i = head[x]; i; i = e[i].next)
    		if (e[i].to != f) dfs(e[i].to, x, v);
    }
    
    int main()
    {
    	for (int T = read(); T--; )
    	{
    		n = read(), m = read();
    		memset(head, 0, (n + 1) << 2), memset(vis, 0, (n + 1) << 2);
    		memset(d, 0, (n + 1) << 2), memset(deg, 0, (n + 1) << 2), e_num = 0;
    		for (int i = 1, a, b; i <= m; i++)
    			a = read(), b = read(), add_edge(a, b), add_edge(b, a);
    		int f = 0;
    		for (int i = 1; !f && i <= n; i++)
    			if (!vis[i]) if ((f = findCir(i, 0))) Set(i);
    		for (int i = 1; !f && i <= n; i++)
    			if (deg[i] > 3) { d[i] = 2, Set(i), f = 1; }
    		for (int i = 1; !f && i <= n; i++)
    			if (deg[i] == 3) if ((f = findDeg(i, 0)))
    				memset(vis, 1, sizeof vis), Set(i);
    		for (int i = 1; !f && i <= n; i++) if (deg[i] == 3)
    		{
    			int cur = 0; vec[0].clear(), vec[1].clear(), vec[2].clear();
    			for (int j = head[i]; j; j = e[j].next) dfs(e[j].to, i, vec[cur++]);
    			if (vec[0].size() > vec[1].size()) std::swap(vec[0], vec[1]);
    			if (vec[0].size() > vec[2].size()) std::swap(vec[0], vec[2]);
    			if (vec[1].size() > vec[2].size()) std::swap(vec[1], vec[2]);
    			if (vec[1].size() == 1 || (vec[0].size() == 1 && vec[1].size() == 2
    					&& vec[2].size() < 5)) continue;
    			f = 1;
    			if (vec[2].size() >= 5)
    			{
    				d[i] = 6, d[vec[0][0]] = 3, d[vec[1][0]] = 4, d[vec[1][1]] = 2;
    				for (int j = 0; j < 5; j++) d[vec[2][j]] = 5 - j;
    			}
    			else
    			{
    				d[i] = (vec[0].size() + 1) * (vec[1].size() + 1) * (vec[2].size() + 1);
    				for (int j = 0; j < 3; j++) for (int k = 0; k < (int) vec[j].size(); k++)
    					d[vec[j][k]] = d[i] / (vec[j].size() + 1) * (vec[j].size() - k);
    			}
    		}
    		if (!f) { puts("NO"); continue; } puts("YES");
    		for (int i = 1; i <= n; i++) printf("%d%c", d[i], " 
    "[i == n]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Git原理与命令大全
    【网络安全】加解密算法最详解
    陪你阅读《区块链:从数字货币到信用社会》序一
    Splunk初识
    红帽学习记录[RHCE] ISCSI远程块储存
    DNS 域名系统与邮件服务器
    红帽学习记录[RHCE] 防火墙与网络合作
    红帽学习笔记[RHCE]网络配置与路由转发
    红帽学习笔记[RHCE]OpenLDAP 服务端与客户端配置
    红帽学习笔记[RHCSA] 第二周
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/11241033.html
Copyright © 2011-2022 走看看