Luogu P1892 [BOI2003]团伙

P1892 [BOI2003]团伙

题目描述

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

  


 

 

先说一下思路:

对于只有朋友信息的数据就不用说了。对于敌人的信息,我们可以给每一个人i设置一个敌人集合E[i],当输入i和j时,我们就把i和E[j]合并,把j和E[i]合并。

值得一提的是,要注意空集的处理,所谓空集就是一开始的时候,每个人都没有敌人。

 

昨天晚上做了一晚上卡在了50分,今天又接着来啃,问同学,同学说我的想法很对,叫我自己慢慢调(WCNM我要是调的出来就不找你了)

没办法,慢慢找喽。

先给大家看看我的50分的代码。

 

#include <iostream>
#include <cstdio>

using namespace std;

int n, m, Ans, x, y;

int f[1008], E[1008];

char C;

bool vis[1008];

int find(int x) {
	if(x == f[x]) return f[x];
	else return f[x] = find(f[x]);
}

int main() {
	scanf("%d%d", &n, &m);
	for(int i=1; i<=n; i++) f[i] = i;
	for(int i=1; i<=m; i++) {
		cin>>C>>x>>y;
		int xx, yy;	
		if(C == 'E') {
			if(E[x] != 0) {
				f[y] = find(E[x]);
			}
			if(E[y] != 0) {
				f[x] = find(E[y]);
			}
			E[x] = y, E[y] = x;
		}
		if(C == 'F') {
			f[x] = find(y);
		}
	}
	for(int i=1; i<=n; i++) {
		if(!vis[find(i)]) {
			vis[find(i)] = 1;
			Ans++;
		}
	}
	printf("%d", Ans);
}

 

  

不知道大家看出什么问题了没。

没看出的同学可要小心了,

看一下我的合并集合时候的操作,是不是把之前合并好的集合都打乱了。

为什么?因为我合并时修改的是f[x]的值,而不是f[find(x)]的值,这就会导致很可怕的错误。

往后的此类操作都是这样的。

好了,说到这里该放上AC的代码了

#include <iostream>
#include <cstdio>

using namespace std;

int n, m, Ans, x, y;

int f[1008], E[1008];

char C;

bool vis[1008];

int find(int x) {
	if(x == f[x]) return x;
	else return f[x] = find(f[x]);
}

int main() {
	scanf("%d%d", &n, &m);
	for(int i=1; i<=n; i++) f[i] = i;
	for(int i=1; i<=m; i++) {
		cin>>C>>x>>y;
		if(C == 'E') {
			if(E[x] != 0) {	
				f[find(y)] = find(E[x]);
			}
			else E[x] = find(y);
			if(E[y] != 0) {
				f[find(x)] = find(E[y]);
			}
			else E[y] = find(x);
		}
		if(C == 'F') {
			f[find(x)] = find(y);
		}
	}
	for(int i=1; i<=n; i++) {
		if(!vis[find(i)]) {
			vis[find(i)] = 1;
			Ans++;
		}
	}
	printf("%d", Ans);
}

  

 

 

posted @ 2018-05-24 22:18  Mystical-W  阅读(293)  评论(2编辑  收藏  举报