[noip模拟]心<并查集>
背景描述:
不是一切深渊都是灭亡
不是一切灭亡都覆盖在弱者的头上
——《这也是一切》 舒婷
有N个透明的盒子, 每个盒子里面有两个不同颜色的球, 总共有M种颜色。
Alice和Bob又在玩游戏, 具体的, Alice会从N个盒子里面选出若干个, Bob再从Alice选出的盒子里面选出一些(不能不选), 如果在Bob选出的盒子中, 每个颜色的球都总共出现了偶数次(0次也是偶数次), 那么Bob胜利, 否则Alice胜利
在Alice和Bob都足够聪明的情况下, Alice想知道自己在能够获胜的前提下, 第一次最多可以选出几个盒子
输入格式:
第一行有两个整数N和M, 意义如题
接下来N行, 第i+1行两个整数表示第i+1个盒子里面的两个球分别是什么颜色的
输出格式:
一行一个整数表示Alice最多可以选多少个盒子
样例输入:
3 3
1 2
2 3
2 3
样例输出:
2
数据规模:
对于30%的数据, N <= 10
对于50%的数据, N <= 20
对于100%的数据, N <= 100000, M <= 2N
可能是我太弱了,我虽然发现了是不能出现环,但是我还是打错了
这是一个并查集,我们把一个盒子的两个颜色看成是一条边连着的两个点,然后并查集组成链状结构
并查集的一个经典处理就是如果两个点不在一个集合就加进同一个集合,然后集合的表示就是这个点当前的祖先,如果开始判断这个点和这个点的祖先这条边时,就说明这条边成环了,就不要选
其实说白了就是一个裸的并查集操作
只是有一个小小细节就是不能单纯的fx=find(x),在这一步操作后,还要把fa[x]变成fx,不然会超时,毕竟这道题这看最终的祖先,途中的都不用管
1 #include<cstdio>
2 #include<cstring>
3 #include<algorithm>
4 #include<cstdlib>
5 #include<cmath>
6 #include<queue>
7 #include<iostream>
8 #define maxn 100005
9 using namespace std;
10 int n,m,fa[2*maxn],ans;
11 int find(int x){
12 if(fa[x]==x)return x;
13 else return find(fa[x]);
14 }
15 int main(){
16 scanf("%d%d",&n,&m);
17 for(int i=1;i<=m;i++){fa[i]=i;}
18 for(int i=1;i<=n;i++){
19 int x,y;
20 scanf("%d%d",&x,&y);
21 int fx=find(x),fy=find(y);
22 fa[x]=find(x);fa[y]=find(y);
23 if(fx!=fy){
24 fa[fx]=fy;ans++;
25 }
26 }cout<<ans;
27 }