ZROI17普及23-B.星空题解--图的灵活转化

题目链接

版权原因不予提供

分析

这题思路很妙啊,虽然已经算半个套路题(因为我太菜了)

将框视为点,若一个球能放在$x$或$y$框,则$x,y$连一条无向边。有一条非常显然的性质是:在联通块中,若有奇数条边,则经过一定能调整使得最少有一个答案贡献,若有奇数条边,则最少对答案没有贡献

这个性质其实非常好想,但我想了挺久找不出合适的话来解释,标程用图来解释就比较直观更好处理

于是我们只要模拟上述过程就好了,一道看似与图无关的题用图就迎刃而解

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <cstdio>
#include <cstring>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <iostream>
#define ll long long
#define ri register int
#define ull unsigned long long
using namespace std;
template <class T>inline void read(T &x){
x=0;int ne=0;char c;
while(!isdigit(c=getchar()))ne=c=='-';
x=c-48;
while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
x=ne?-x:x;return ;
}
const int maxn=200005;
const int inf=0x7fffffff;
int n,m;
int fa[maxn],num[maxn];
int get(int x){return (x==fa[x])?fa[x]:(fa[x]=get(fa[x]));}
int main(){
int x,y;
srand(19260817);//闷声发大财 预祝长者大寿 Long Live Jiang !!!
read(n),read(m);
for(ri i=1;i<=m;i++)fa[i]=i;
for(ri i=1;i<=n;i++){
read(x),read(y);
x=get(x),y=get(y);
if(x==y)num[x]++;
else {
fa[x]=y;
num[y]=num[y]+num[x]+1;
}
}
ll ans=0;
for(ri i=1;i<=m;i++){
if(i==fa[i])ans+=(num[i]%2);
}
printf("%lld\n",ans);
return 0;
}