agc032_c
题解
每个节点的度数必然是偶数。因为每个环中的结点是偶数,所以合起来也是偶数。
利用这再结合边数至少为点数 \(+2\) 就可以骗到挺多的分数哦。
考虑看每个结点的度数看回路的数量。
如果存在一个节点的度数 \(\ge 6\) ,那么这个图的回路必然经过这个结点三次。所以必然可以拆成三个环。
那么剩下就是节点度数为\(2\) 或者\(4\) 。如果所有节点度数均为 \(2\) ,那么这张图是一个环。显然不行。剩下情况考虑将所有度数为 \(2\) 的点都「缩掉」,也就是把读书为 \(2\) 的点看成一条边。那么剩下的就只有度数为 \(4\) 的点了。那么分为三种情况讨论:
- 度数为 \(4\) 的点至少有3个。有解。
- 度数为 \(4\) 的点只有 \(2\) 个。
- 度数为 \(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;
}