题目描述
1920年的芝加哥,出现了一群强盗。如果两个强盗遇上了,那么他们要么是朋友,要么是敌人。而且有一点是肯定的,就是:
我朋友的朋友是我的朋友;
我敌人的敌人也是我的朋友。
两个强盗是同一团伙的条件是当且仅当他们是朋友。现在给你一些关于强盗们的信息,问你最多有多少个强盗团伙。
输入格式
输入文件gangs.in的第一行是一个整数N(2<=N<=1000),表示强盗的个数(从1编号到N)。 第二行M(1<=M<=5000),表示关于强盗的信息条数。 以下M行,每行可能是F p q或是E p q(1<=p q<=N),F表示p和q是朋友,E表示p和q是敌人。输入数据保证不会产生信息的矛盾。
输出格式
输出文件gangs.out只有一行,表示最大可能的团伙数。
输入输出样例
输入 #1复制
6 4 E 1 4 F 3 5 F 4 6 E 1 2
输出 #1复制
3
思路
显然的并查集。用enemy[i]记录i的敌人,fa[i]记录i的祖先。
#include <stdio.h>
#include <iostream>
#define N 1001
using namespace std;
int n,m,s,fa[N],enemy[N],cnt[N];
int getfind(int v)
{
if(fa[v]==v) return v;
else
{
fa[v]=getfind(fa[v]);
return fa[v];
}
}
inline void merge(int v,int u)
{
register int t1,t2;
t1=getfind(v);
t2=getfind(u);
if(t1!=t2)
{
fa[t2]=t1;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
register int i,j;
cin>>n>>m;
for(i=1;i<=n;i++)
{
fa[i]=i;
}
for(i=1;i<=m;i++)
{
char c;
int u,v;
cin>>c>>u>>v;
if(c=='F') merge(u,v);//合并朋友
else
{
if(enemy[u]==0)
{
enemy[u]=getfind(v);
}
else
{
merge(enemy[u],v);
}
if(enemy[v]==0)
{
enemy[v]=getfind(u);
}
else
{
merge(u,enemy[v]);
}
}
}
for(i=1;i<=n;i++)//统计独立的团伙
{
cnt[getfind(i)]++;
}
for(i=1;i<=n;i++)
{
if(cnt[i]) s++;
}
cout<<s<<endl;
return 0;
}