RT
题目描述
1920年的芝加哥,出现了一群强盗。如果两个强盗遇上了,那么他们要么是朋友,要么是敌人。而且有一点是肯定的,就是:
我朋友的朋友是我的朋友;
我敌人的敌人也是我的朋友。
两个强盗是同一团伙的条件是当且仅当他们是朋友。现在给你一些关于强盗们的信息,问你最多有多少个强盗团伙。
输入输出格式
输入格式:
输入的第一行是一个整数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是敌人。输入数据保证不会产生信息的矛盾。
输出格式:
输出只有一行,表示最大可能的团伙数。
输入: 输出:
6 3
4
E 1 4
F 3 5
F 4 6
E 1 2
一看这题,是一道并查集的好 水 题,但好像和以往的不太一样;
想一想,好像是个数学集合;
把朋友并一起,把敌人的敌人并到朋友;
par[n]存 朋友,par[n*2]存敌人;
然后就好了;
#include <cstdio> #include <algorithm> using namespace std; struct b { int par[100010]; inline void ih(int n){for(int i=1;i<=2*n;i++)par[i]=i;} int f(int x){ return par[x]=(par[x]==x)?x:f(par[x]); } int u(int x,int y){par[f(y)]=f(x);} }s; int n,m,sum; int x,y; char c; int main() { scanf("%d",&n); scanf("%d",&m); s.ih(n); for(int i=1;i<=m;++i) { scanf("%s%d%d",&c,&x,&y); if(c==‘F‘) { s.u(x,y); } else if(c==‘E‘) { s.u(y,x+n); //不要并反了 s.u(x,y+n); } } for(int i=1;i<=n;++i) { if(s.par[i]==i) sum++; } printf("%d",sum); }