说明
芝加哥组织了一场激烈的军事竞赛,很多国家的军人慕名而来,他们要么是队友,要么是敌人。
现建立如下规则:
我的队友的队友,是我的队友;
我的敌人的敌人也是我的队友;
两个人只要是队友,就认为他们属于同一团队,现给你若干参赛军人之间的关系,请问:最多有多少个团队?
输入格式
第一行是一个整数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是敌人。输入数据保证不会产生信息的矛盾。
输出格式
输出文件只有一行,表示最大可能的团队数。
样例
输入数据 1
6
4
E 1 4
F 3 5
F 4 6
E 1 2
Copy
输出数据 1
3
Copy
提示
样例结束:[3,5]是一个团队,[4,6]是一个团队,由于1和4、1和2都是敌人,2和4自然成为队友,因此[2,4,6]成为团队,1单独为1个团队,最终有3个团队。
才两三天感觉思路都忘了。。。。😢
这是一道并查集题
反思总结:
1、如果读入是敌人,就记录下来
2、如果读入是队友,直接合并
3、读入数据完成后,将敌人的敌人合并为一个集合
4、最后循环判断集合数即可
注意:
1、因为不知道敌人有多少个,所以使用vector数组存放敌人。
2、在两个两个的合并敌人的时候,注意不要越界,原因就是vector越界会出现随机数,而不是 0 (防止越界的方法就是 j+1<b[i].size())
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
using namespace std;
#define ll long long
int n,m;
char t;
int fa[5007];
vector<int> b[5007];
int vis[5007];
void init() {
for(int i=1; i<=n; i++) {
fa[i]=i;
}
}
int find(int x) {
int temp=x;
while(fa[temp]!=temp) {
temp=fa[temp];
}
while(x!=fa[x]) {
int re=fa[x];
fa[x]=temp;
x=re;
}
return x;
}
void merge(int x,int y) {
int u=find(x);
int v=find(y);
if(u!=v) {
fa[u]=v;
}
}
int main() {
cin>>n>>m;
init();
for(int i=0; i<m; i++) {
cin>>t;
if(t=='E') {
int temp=0;
cin>>temp;
int xx;
cin>>xx;
b[temp].push_back(xx);
} else {
int temp=0,xx=0;
cin>>temp>>xx;
merge(temp,xx);
}
}
for(int i=1; i<=n; i++) {
for(int j=0; j+1<b[i].size(); j++) {//防止越界的方法就是 j+1<b[i].size()
if(b[i][j]!=0&&b[i][j+1]!=0) {//越界的数值不是0,而是随机的数值
merge(b[i][j],b[i][j+1]);
} else
break;
}
}
int ans=0;
for(int i=1; i<=n; i++) {
int temp=find(i);
if(!vis[temp]) {
vis[temp]=1;
ans++;
}
}
cout<<ans<<endl;
return 0;
}