其他分享
首页 > 其他分享> > 团伙

团伙

作者:互联网

题目:

 团伙

题目链接:https://www.luogu.com.cn/problem/T241093?contestId=69902

题目描述

现在有 nn 个人,他们之间有两种关系:朋友和敌人。我们知道:

现在要对这些人进行组团。两个人在一个团体内当且仅当这两个人是朋友。请求出这些人中最多可能有的团体数。

输入格式

第一行输入一个整数 nn 代表人数。

第二行输入一个整数 mm 表示接下来要列出 mm 个关系。

接下来 mm 行,每行一个字符 optopt 和两个整数 p,qp,q,分别代表关系(朋友或敌人),有关系的两个人之中的第一个人和第二个人。其中 optopt 有两种可能:

输出格式

一行一个整数代表最多的团体数。

输入输出样例

输入 #1
6
4
E 1 4
F 3 5
F 4 6
E 1 2
输出 #1
3

说明/提示

对于 100\%100% 的数据,2 \le n \le 10002≤n≤1000,1 \le m \le 50001≤m≤5000,1 \le p,q \le n1≤p,q≤n。

解题思路:

这道题是一个并查集,用father函数来进行合并父亲结点。

首先,如果两人是朋友,那么就把两人合并。

除此之外,我们再维护一个e[i],表示i的一个敌人。如果两人是敌人,那么如果e[i]为空,就更新e[i],否则,就把e[i]和j合并。根据敌人的敌人是朋友的原则,如果j和i是敌人,那么j同e[i]则是朋友,所以合并。同样的,对于i和e[j],也是如此。最后统计一下根结点就行了。

参考代码:

#include<iostream>
using namespace std;
int root[1001]={0};
int relate[1001][1001]={0};
int father(int n){
if (root[n]==-1)
   {
   return n;
   }
else return father(root[n]);
}

int hb(int x,int y){
int n,m;
n=father(x);
m=father(y);
if (n<m){
   root[m]=n;
   }
else {
   root[n]=m;
   }
return 0;
}
int mains(){
int n,m;
int i,j,k;
char c;
int x,y;
cin>>n>>m;
for (i=1;i<=1001;i++)
   {
   root[i]=-1;
   }
for (i=1;i<=m;i++)
   {
   cin>>c>>x>>y;
   if (c=='E')
    {
    relate[y][x]=1;//记录相互的关系
    relate[x][y]=1;
    }
   if (c=='F')
    {
    hb(x,y);
    }
}
for (i=1;i<=n;i++){//遍历关系,合并我的敌人的敌人即朋友
   for (j=1;j<i;j++)//通过以当前位置的前一位置向下辐射,即每次查找一个方阵
    {
    if(relate[i][j]){
     for (k=1;k<i;k++)//小于i是为了防止二次合并,即构成方阵
      {
      if (relate[j][k])
       {
       hb(k,i);
       }
      }
     }
   }
   cout<<endl;
}
int s=0;
for (i=1;i<=n;i++)
   {
   if (root[i]==-1)s++;
   }
cout<<s;

return 0;
}

标签:le,int,relate,father,朋友,root,团伙
来源: https://www.cnblogs.com/kenty/p/16412618.html