agc032_c

agc032_c

题解

每个节点的度数必然是偶数。因为每个环中的结点是偶数,所以合起来也是偶数。

利用这再结合边数至少为点数 \(+2\) 就可以骗到挺多的分数哦。

考虑看每个结点的度数看回路的数量。

如果存在一个节点的度数 \(\ge 6\) ,那么这个图的回路必然经过这个结点三次。所以必然可以拆成三个环。

那么剩下就是节点度数为\(2\) 或者\(4\) 。如果所有节点度数均为 \(2\) ,那么这张图是一个环。显然不行。剩下情况考虑将所有度数为 \(2\) 的点都「缩掉」,也就是把读书为 \(2\) 的点看成一条边。那么剩下的就只有度数为 \(4\) 的点了。那么分为三种情况讨论:

  1. 度数为 \(4\) 的点至少有3个。有解。
  2. 度数为 \(4\) 的点只有 \(2\) 个。
  3. 度数为 \(4\) 的点只有一个。无解。

其中第二种情况还需要细分一下,如果这两个结点之间有四条边,必然不行。否则必然是两个节点之间有两条边,各自有一个自环,这是可以的。

总结

  • 可以考虑根据结点度数研究换的问题。

代码

用一个Dfs随便判断一下是那种情况就行(度数为 \(2\) 的哪种情况)

很明显和小粉兔写的非常像,这是因为我参照了他的题解。。。

#include <cstdio>
#include <vector>
using namespace std;
const int NM = 1e5 + 5;
int n, m, deg[NM], c4, stk[NM], tp, cnt;
vector<int> G[NM];
bool vis[NM];
void DFS(int u) {
	vis[u] = 1, ++cnt;
	for (int v : G[u]) if (!vis[v]) DFS(v);
}
int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; ++i) {
		int u, v;
		scanf("%d%d", &u, &v);
		G[u].push_back(v);
		G[v].push_back(u);
		++deg[u];
		++deg[v];
	}
	for (int i = 1; i <= n; ++i) {
		if (deg[i] & 1) {
			printf("No\n");
			return 0;
		}
		if (deg[i] == 4)
			stk[++c4] = i;
	}
	for (int i = 1; i <= n; ++i) {
		if (deg[i] >= 6) {
			printf("Yes\n");
			return 0;
		}
	}
	if (c4 >= 3) {
		printf("Yes\n");
		return 0;
	} else if (c4 == 2) {
		vis[stk[2]] = 1;
		DFS(stk[1]);
		if (cnt == n - 1)
			printf("No\n");
		else printf("Yes\n");
	} else
		printf("No\n");
	return 0;
}
posted @ 2020-07-11 18:16  acniu  阅读(132)  评论(0编辑  收藏  举报