原题传送门
前置知识:并查集,不会的补了再来。
这道题只是在并查集的基础上多了一个操作而已。
这种操作,叫做反集(就先这么叫着)
题目里有一种关系是互为朋友,这很好理解,把互为朋友的两个点合并就可以了。
互为敌人怎么办?
用反集!
所谓反集,就是分别把x,y和它们对应的虚点连接起来。(虚点:a的虚点是a+n(点数))
因为一个人不可能和自己是敌人(至少这道题里不会),所以x永远不会和x+n连接起来,但如果x和y+n连接起来了,x和y就永远不会在一个并查集里了。
有了这个特性,最后检查的时候遍历一遍1-n,如果它是根节点就ans++,最后输出即可。
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,fa[],x,y,sz[];
char o;
void init()
{
for(int i=;i<=;i++)
{
fa[i]=i;
sz[i]=;
}
}
int get(int x)
{
if(fa[x]==x)return x;
int r=get(fa[x]);
fa[x]=r;
return r;
}
void merge(int x,int y)
{
int r1=get(x),r2=get(y);
if(r1==r2)
{
return;
}
fa[r1]=r2;
sz[r2]+=sz[r1];
return;
}
int main()
{
cin>>n>>m;
init();
for(int i=;i<=m;i++)
{
cin>>o>>x>>y;
if(o=='F')merge(x,y);
else
{
merge(y+n,x);
merge(x+n,y);
}
}
int ans=;
for(int i=;i<=n;i++)
{
if(fa[i]==i)ans++;
}
cout<<ans<<endl;
return ;
}