题意

不是一切深渊都是灭亡
不是一切灭亡都覆盖在弱者的头上
——《这也是一切》 舒婷

NN 个透明的盒子,每个盒子里面有两个不同颜色的球,总共有 MM 种颜色。Alice 和 Bob 又在玩游戏,具体的,Alice 会从 NN 个盒子里面选出若干个,Bob 再从 Alice 选出的盒子里面选出一些(不能不选),如果在 Bob 选出的盒子中,每个颜色的球都总共出现了偶数次(00 次也是偶数次),那么 Bob 胜利,否则 Alice 胜利。在 Alice 和 Bob 都足够聪明的情况下,Alice 想知道自己在能够获胜的前提下, 第一次最多可以选出几个盒子。

这道题其实很水,就是需要转换一下。还有一定要开够数组!!!

我们先讲第一个思路:把每个盒子看成一条边,每条边两端有两个不同颜色的小球,那么要满足的条件就是,Alice 选中的边必须无环。(因为如果有环,那么必定有一个球选中了偶数次)。

我们把所有的盒子当成边建一个图,会出现很多个连通块,我们只需要把每个联通分块修改成一棵树,那么肯定不会出现环(修改成一棵树,那么边数为连通块中的点数减一)。所以我们把每个连通块的点数求出来,依次相加即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=100005;
const int maxm=200005;
using namespace std;
int np=0,first[maxm]={0},cc=0,n,m,ans=0;
int belong[maxm],num[maxm];
struct graph
{
	int next,to;
}G[maxn<<1];
void add(int u,int v)
{
	G[++np]=(graph){first[u],v};
	first[u]=np;
}
void dfs(int s)
{
    for(int p=first[s];p;p=G[p].next)
    {
        int j=G[p].to;
        if(!belong[j])
        {
            belong[j]=belong[s];
            dfs(j);
        }
    }
}
int main()
{
   freopen("heart.in","r",stdin);
   freopen("heart.out","w",stdout);
    memset(belong,0,sizeof(belong));
    memset(num,0,sizeof(num));
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    {
    	int a,b;
         scanf("%d%d",&a,&b);
         add(a,b);
         add(b,a);
    }
    for (int i=1;i<=m;i++)
    {
        if(!belong[i])
		{
			belong[i]=++cc;
            dfs(i);
		 }
    }
    for (int i=1;i<=m;i++)
        num[belong[i]]++;
    for (int i=1;i<=cc;i++)
        ans+=(num[i]-1);
    printf("%d",ans);
    return 0;
}

第二种思路就是用并查集来维护。

我们每次对于一个盒子,把两个球合并,如果以后再遇到一个盒子中,两个球同属于同一个集合,则说明它们都被选过了,肯定会产生偶数个,就直接跳过。

于是代码超级水:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=2e5+1010;
int n,m,fa[maxn],ans;
int getfa(int x)
{
	if(fa[x]==x)
		return x;
	return fa[x]=getfa(fa[x]);
}
void merge(int a,int b)
{
	int x=getfa(a);
	int y=getfa(b);
	if(x!=y)
	{
		fa[x]=y;
		ans++;
	}
}
int main()
{
	freopen("heart.in","r",stdin);
	freopen("heart.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
		fa[i]=i;
	for(int i=1;i<=n;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		if(getfa(a)!=getfa(b))
			merge(a,b);
		else
			continue;
	}
	printf("%d",ans);
	return 0;
}