标签:col set 奇数 can 循环 while ons strong space
题意很简单,爆搜的时间复杂度比较高,不考虑。
应该使用欧拉回路的相关知识求解。
输入时将两个节点的入度都加一(无向),然后将两个节点合并在一个连通图中.
for (int i = 1, u, v; i <= m; i++) {
scanf ("%d %d", &u, &v);
in[v] ++, in[u] ++;
UnionSet(u, v);
}
从1~n循环,依次枚举,记录每个连通图中的点数。
用一个ans[]数组保存连通图中度为奇数的节点。
再枚举一遍
如果一个连通图中的节点数不大于1,就不用画,跳过。
如果ans[]为0,这次图是一个欧拉回路,就sum++
如果ans[]不为零 sum += ans[]/2
因为一笔只能够画掉两个奇数度数的节点 (因为TFW不停问,特此强调) ,所以只加上ans[]/2
#include <vector>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1e5 + 5;
int n, m, sum;
int in[MAXN], num[MAXN], ans[MAXN], fa[MAXN];
/* num -> 保存一个连通块里有几个节点*/
int FindSet(int v) {
if (fa[v] == v) return v;
else return fa[v] = FindSet(fa[v]);
}
void UnionSet(int u, int v) {
int x = FindSet(u);
int y = FindSet(v);
if (x == y) return ;
else fa[x] = y;
}
int main() {
while (scanf ("%d %d", &n, &m) != EOF) {
sum = 0;
for (int i = 1; i <= n; i++) {
fa[i] = i;
ans[i] = 0;
num[i] = 0;
in[i] = 0;
}
for (int i = 1, u, v; i <= m; i++) {
scanf ("%d %d", &u, &v);
in[v] ++, in[u] ++;
UnionSet(u, v);
}
for (int i = 1; i <= n; i++) {
num[FindSet(i)] ++;
if (in[i] % 2 == 1) {
ans[FindSet(i)] ++;
}
}
for (int i = 1; i <= n; i++) {
if (num[i] <= 1) continue;
if (ans[i] == 0) sum ++;
else {
sum += ans[i] / 2;
}
}
printf ("%d\n", sum);
}
return 0;
}
标签:col set 奇数 can 循环 while ons strong space
原文地址:https://www.cnblogs.com/cqbz-ChenJiage/p/13537688.html