团伙 并查集_BZOJ 1370 [Baltic2003]Gang团伙 并查集

题意:

朋友的朋友是我的朋友,敌人的敌人是我的朋友。

n(<=1000)个人给出m(<=5000)对关系表示谁与谁是朋友关系或者是敌对关系。

询问这n个人最多分多少团伙。

解析:

原来做的那个是这个的弱化版…只有朋友关系….

然后这个的话敌对关系我们可以用一种巧妙地拆点法,注意这个方法也是为了秉行上面的那个朋友的朋友…..

朋友关系我们直接合并即可。

敌对关系的话,我们可以考虑把x拆成x与x+n,x+n如果代表与x敌对的话,恰好可以满足我们秉行的那句话,然后最后我们统计一下所有点有多少个不同的团伙即可。

挺有意思的拆点法…

另外,我尝试封装了下并查集,感觉萌萌哒。

代码:

#include

#include

#include

#include

#define N 2010

using namespace std;

class Union_Find_Set

{

public:

int fa

;

Union_Find_Set(int n)

{

for(int i=1;i<=n;i++)

size[i]=1,fa[i]=i;

}

int find(int x)

{

if(fa[x]==x)return x;

return fa[x]=find(fa[x]);

}

void Union(int x,int y)

{

x=find(x),y=find(y);

if(x!=y)

{

if(size[x]>size[y])swap(x,y);

fa[x]=y;

size[y]+=size[x];

}

}

private:int size

;

}UFS(N-1);

int n,m;

char s[2];

int a

;

int main()

{

scanf("%d%d",&n,&m);

for(int i=1;i<=m;i++)

{

int x,y;

scanf("%s%d%d",s,&x,&y);

if(s[0]=='E')

UFS.Union(x+n,y),UFS.Union(y+n,x);

else UFS.Union(x,y);

}

for(int i=1;i<=n;i++)a[i]=UFS.find(i);

sort(a+1,a+n+1);

int ans=0;

for(int i=1;i<=n;i++)

if(a[i]!=a[i-1])ans++;

printf("%d\n",ans);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值