GitBook

这里写图片描述 输入输出

上次个人赛出了这一题 不过当时用的搜索的思维来写的

大概就是遇见一个人感染 则寻找所有社团中包含这个人的社团 并分别对每一个成员递归

#include<stdio.h>
#include<string.h>
int n,z,cnt;
int a[500][1000];
int b[30000];
void s(int m) {
	if(!b[m]) {
		cnt++;
		b[m]=1;
	} else
		return ;
	for(int i=0; i<z; i++) {
		for(int j=1; j<=a[i][0]; j++) {
			if(a[i][j]==m) {
				for(int k=1; k<=a[i][0]; k++) {
					if(a[i][k]!=m)
						s(a[i][k]);
				}
				break;
			}
		}
	}
}
int main() {
	while(scanf("%d %d",&n,&z),n!=0||z!=0) {
		memset(b,0,sizeof(b));
		memset(a,0,sizeof(a));
		for(int i=0; i<z; i++) {
			scanf("%d",&a[i][0]);
			for(int j=1; j<=a[i][0]; j++) {
				scanf("%d",&a[i][j]);
			}
		}
		cnt=0;
		s(0);
		printf("%d\n",cnt);
	}
	return 0;
}

不过这一题用并查集的思想还是更为简便一些

也就是直接根据社团关系来合并集合 然后最后查找有几个和 0 号在同一个集合

#include<stdio.h>
int par[30200];
int rank[30200];
int find(int m) {
	if(m==par[m])
		return m;
	else
		return par[m]=find(par[m]);
}
void unite(int x,int y) {
	x=find(x);
	y=find(y);
	if(x==y)
		return;
	if(rank[x]<rank[y])
		par[x]=y;
	else {
		par[y]=x;
		if(rank[x]==rank[y])
			rank[x]++;
	}
}
int main() {
	int n,m;
	while(scanf("%d %d",&n,&m),n||m) {
		for(int i=0; i<n; i++) {
			par[i]=i;
			rank[i]=0;
		}
		for(int i=0; i<m; i++) {
			int k;
			scanf("%d",&k);
			int t;
			scanf("%d",&t);
			k--;
			while(k--) {
				int p;
				scanf("%d",&p);
				unite(t,p);
				t=p;
			}
		}
		int cnt=0;
		for(int i=0; i<n; i++) {
			if(find(i)==find(0))
				cnt++;
		}
		printf("%d\n",cnt);
	}
	return 0;
}

题目地址:【POJ】[1611]The Suspects