并查集-朋友问题
2012-12-10 23:15
204 查看
例一:
整个组织有n个人,任何两个认识的人不是朋友就是敌人,而且满足:①我朋友的朋友是我的朋友;②我敌人的敌人是我的朋友。所有是朋友的人组成一个团伙。现在,警方委派你协助调查,拥有关于这n个人的m条信息(即某两个人是朋友,或某两个人是敌人),请你计算出这个城市最多可能有多少个团伙。
数据范围:2≤N≤1000,1≤M≤1000。
输入数据:第一行包含一个整数N,第二行包含一个整数M,接下来M行描述M条信息,内容为以下两者之一:“F
x y”表示x与y是朋友;“E x y”表示x与y是敌人(1≤x≤y≤N)。
输出数据:包含一个整数,即可能的最大团伙数。
样例:
输入:6
4
E 1 4
F 35
F 4 6
E 1 2
输出:3
#include<iostream>
using namespace std;
int root[1001]={0};
int relate[1001][1001]={0};
int father(int n){
if (root
==-1)
{
return n;
}
else return father(root
);
}
int hb(int x,int y){
int n,m;
n=father(x);
m=father(y);
if (n<m){
root[m]=n;
}
else {
root
=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;
}/*首先,如果两人是朋友,那么就把两人合并。
除此之外,我们再维护一个e[i],表示i的一个敌人。如果两人是敌人,那么如果e[i]为空,就更新e[i],否则,就把e[i]和j合并。根据敌人的敌人是朋友的原则,如果j和i是敌人,那么j同e[i]则是朋友,所以合并。同样的,对于i和e[j],也是如此。最后统计一下根结点就行了。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
int n,m;
const int maxn=1000;
int f[maxn+10],e[maxn+10];
int find(int x)
{
if (f[x]==x) return f[x];
f[x]=find(f[x]);
return f[x];
}
void together(int a,int b)
{
int aa=find(a),bb=find(b);
f[aa]=f[bb];
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1; i<=n; i++)
f[i]=i;
while (m--)
{
char flag=(getchar(),getchar());
int a,b;
scanf("%d%d",&a,&b);
if (flag=='F') together(a,b);
else
{
if (!e[a]) e[a]=b;
else together(e[a],b);
if (!e) e[b]=a;
else together(e[b],a);
}
}
int ans=0;
for (int i=1; i<=n; i++)
if (f[i]==i) ans++;
printf("%d\n",ans);
return 0;
}
*/
例二:
[b]More isbetter
Time Limit: 5000/1000 MS (Java/Others) Memory Limit:327680/102400 K (Java/Others)
Total Submission(s): 7622 Accepted Submission(s): 2797
Problem Description
Mr Wang wants some boys tohelp him with a project. Because the project is rather complex,
the moreboys come, the better it will be. Of course there are certain requirements.
Mr Wang selected a room big enough to hold the boys. The boy who are not beenchosen has to leave the room immediately. There are 10000000 boys in the roomnumbered from 1 to 10000000 at the very beginning. After Mr Wang's selectionany two of them who are still
in this room should be friends (direct orindirect), or there is only one boy left. Given all the direct friend-pairs,you should decide the best way.
Input
The first line of the inputcontains an integer n (0 ≤ n ≤ 100 000) - the number of direct friend-pairs.The following n lines each contains a pair of numbers A and B separated by asingle space that suggests A and
B are direct friends. (A ≠ B, 1 ≤ A, B ≤10000000)
Output
The output in one linecontains exactly one integer equals to the maximum number of boys Mr Wang maykeep.
Sample Input
4
1 2
3 4
5 6
1 6
4
1 2
3 4
5 6
7 8
Sample Output
4
2
Hint
A and B are friends(direct or indirect), B and C are friends(direct orindirect),
then A and C are also friends(indirect).
In the first sample {1,2,5,6} isthe result.
In the second sample {1,2},{3,4},{5,6},{7,8} are four kinds of answers.
#include<stdio.h>
#include<string.h>
intf[10000001];
boolroot[10000001];
intsum=0;
intfind(int a);
voidUnino(int a,intb);
intmain(void){
int n,a,b;
while(scanf("%d",&n)!=EOF){
for(intj=0;j<10000001;j++){
root[j]=true;
f[j]=1;
}
for(inti=0;i<n;i++){
scanf("%d%d",&a,&b);
a=find(a);
b=find(b);
if(a!=b){
Unino(a,b);
}
}
for(intk=0;k<10000001;k++){
if(f[k]>sum&&root[k])
sum=f[k];
}
printf("%d\n",sum);
sum=0;
}
return 0;
}
intfind(int a){
while(!root[a])a=f[a];
return a;
}
voidUnino(int a,intb){
if(f[a]>f[b]){
f[a]=f[a]+f[b];
f[b]=a;
root[b]=false;
}
else{
f[b]=f[a]+f[b];
f[a]=b;
root[a]=false;
}
}
整个组织有n个人,任何两个认识的人不是朋友就是敌人,而且满足:①我朋友的朋友是我的朋友;②我敌人的敌人是我的朋友。所有是朋友的人组成一个团伙。现在,警方委派你协助调查,拥有关于这n个人的m条信息(即某两个人是朋友,或某两个人是敌人),请你计算出这个城市最多可能有多少个团伙。
数据范围:2≤N≤1000,1≤M≤1000。
输入数据:第一行包含一个整数N,第二行包含一个整数M,接下来M行描述M条信息,内容为以下两者之一:“F
x y”表示x与y是朋友;“E x y”表示x与y是敌人(1≤x≤y≤N)。
输出数据:包含一个整数,即可能的最大团伙数。
样例:
输入:6
4
E 1 4
F 35
F 4 6
E 1 2
输出:3
#include<iostream>
using namespace std;
int root[1001]={0};
int relate[1001][1001]={0};
int father(int n){
if (root
==-1)
{
return n;
}
else return father(root
);
}
int hb(int x,int y){
int n,m;
n=father(x);
m=father(y);
if (n<m){
root[m]=n;
}
else {
root
=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;
}/*首先,如果两人是朋友,那么就把两人合并。
除此之外,我们再维护一个e[i],表示i的一个敌人。如果两人是敌人,那么如果e[i]为空,就更新e[i],否则,就把e[i]和j合并。根据敌人的敌人是朋友的原则,如果j和i是敌人,那么j同e[i]则是朋友,所以合并。同样的,对于i和e[j],也是如此。最后统计一下根结点就行了。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
int n,m;
const int maxn=1000;
int f[maxn+10],e[maxn+10];
int find(int x)
{
if (f[x]==x) return f[x];
f[x]=find(f[x]);
return f[x];
}
void together(int a,int b)
{
int aa=find(a),bb=find(b);
f[aa]=f[bb];
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1; i<=n; i++)
f[i]=i;
while (m--)
{
char flag=(getchar(),getchar());
int a,b;
scanf("%d%d",&a,&b);
if (flag=='F') together(a,b);
else
{
if (!e[a]) e[a]=b;
else together(e[a],b);
if (!e) e[b]=a;
else together(e[b],a);
}
}
int ans=0;
for (int i=1; i<=n; i++)
if (f[i]==i) ans++;
printf("%d\n",ans);
return 0;
}
*/
例二:
[b]More isbetter
Time Limit: 5000/1000 MS (Java/Others) Memory Limit:327680/102400 K (Java/Others)
Total Submission(s): 7622 Accepted Submission(s): 2797
Problem Description
Mr Wang wants some boys tohelp him with a project. Because the project is rather complex,
the moreboys come, the better it will be. Of course there are certain requirements.
Mr Wang selected a room big enough to hold the boys. The boy who are not beenchosen has to leave the room immediately. There are 10000000 boys in the roomnumbered from 1 to 10000000 at the very beginning. After Mr Wang's selectionany two of them who are still
in this room should be friends (direct orindirect), or there is only one boy left. Given all the direct friend-pairs,you should decide the best way.
Input
The first line of the inputcontains an integer n (0 ≤ n ≤ 100 000) - the number of direct friend-pairs.The following n lines each contains a pair of numbers A and B separated by asingle space that suggests A and
B are direct friends. (A ≠ B, 1 ≤ A, B ≤10000000)
Output
The output in one linecontains exactly one integer equals to the maximum number of boys Mr Wang maykeep.
Sample Input
4
1 2
3 4
5 6
1 6
4
1 2
3 4
5 6
7 8
Sample Output
4
2
Hint
A and B are friends(direct or indirect), B and C are friends(direct orindirect),
then A and C are also friends(indirect).
In the first sample {1,2,5,6} isthe result.
In the second sample {1,2},{3,4},{5,6},{7,8} are four kinds of answers.
#include<stdio.h>
#include<string.h>
intf[10000001];
boolroot[10000001];
intsum=0;
intfind(int a);
voidUnino(int a,intb);
intmain(void){
int n,a,b;
while(scanf("%d",&n)!=EOF){
for(intj=0;j<10000001;j++){
root[j]=true;
f[j]=1;
}
for(inti=0;i<n;i++){
scanf("%d%d",&a,&b);
a=find(a);
b=find(b);
if(a!=b){
Unino(a,b);
}
}
for(intk=0;k<10000001;k++){
if(f[k]>sum&&root[k])
sum=f[k];
}
printf("%d\n",sum);
sum=0;
}
return 0;
}
intfind(int a){
while(!root[a])a=f[a];
return a;
}
voidUnino(int a,intb){
if(f[a]>f[b]){
f[a]=f[a]+f[b];
f[b]=a;
root[b]=false;
}
else{
f[b]=f[a]+f[b];
f[a]=b;
root[a]=false;
}
}
相关文章推荐
- 小米面试题——并查集(关于朋友圈问题)
- POJ1182 并查集 食物链 比较难想到 的问题 并查集 中层次 题
- Union-Find(并查集): Dynamic Connectivity 问题
- java程序System.out.println()中文乱码,很奇怪的问题,知道朋友给我留言告诉我!
- nyoj 一笔画问题(并查集,欧拉路)
- 答某位朋友邮件中关于编程风格的问题
- 用并查集求解连通分量问题
- 为一个朋友解答的C++小问题
- nyoj 42 一笔画问题 dfs或并查集判断连通
- 简单的c语言问题,其实,很多刚入门的朋友弄不明白
- POJ2524-宗教问题-并查集-ACM
- 帮 论坛朋友解决的问题。
- 一个字符串到数组的例子 - 回复"成红"的问题, 对其他朋友参考价值不大
- 和朋友的聊天记录,讨论了.Net 和 J2EE的问题。
- 单词,紫书P169UVa10129(有向图求欧拉路径问题,并查集求连通分支)
- hd1232 修路最少(并查集问题)
- 跪请众朋友帮我找下问题出在哪里?--4
- 微访谈之2:解答各位朋友关心的问题
- 问题 1433: [蓝桥杯][历届试题]危险系数(并查集and暴力)
- 【九度OJ】:1526 并查集 朋友圈问题