1107. Social Clusters (30)
When register on a social network, you are always asked to specify your hobbies in order to find some potential friends with the same hobbies. A "social cluster" is a set of people who have some of their hobbies in common. You are supposed to find all the clusters.
Input Specification:
Each input file contains one test case. For each test case, the first line contains a positive integer N (<=1000), the total number of people in a social network. Hence the people are numbered from 1 to N. Then N lines follow, each gives the hobby list of a person in the format:
Ki: hi[1] hi[2] ... hi[Ki]
where Ki (>0) is the number of hobbies, and hi[j] is the index of the j-th hobby, which is an integer in [1, 1000].
Output Specification:
For each case, print in one line the total number of clusters in the network. Then in the second line, print the numbers of people in the clusters in non-increasing order. The numbers must be separated by exactly one space, and there must be no extra space at the end of the line.
Sample Input:8 3: 2 7 10 1: 4 2: 5 3 1: 4 1: 3 1: 4 4: 6 8 1 5 1: 4Sample Output:
3 4 3 1
#include<stdio.h>
#include<algorithm>
using namespace std;
int hobbyfather[1010]={0};
int father[1010];
int n;
bool cmp(int a,int b){
return a>b;
}
void initial(){
int i;
for(i=1;i<=n;i++){
father[i]=i;
}
}
int findfather(int a){
int x=a;
while(a!=father[a]){
a=father[a];
}
while(x!=father[x]){
int z=x;
x=father[x];
father[z]=a;
}
return a;
}
void UNION(int a,int b){
int fa=findfather(a);
int fb=findfather(b);
if(fa!=fb){
father[fb]=fa;
}
}
int main(){
scanf("%d",&n);
int i,j;
int num[1010]={0};
initial();
for(i=1;i<=n;i++){
int b;
scanf("%d: ",&b);
for(j=1;j<=b;j++){
int c;
scanf("%d",&c);
if(hobbyfather[c]!=0){//已经有hobbyfather[c]提及了这个hobby,将hobbyfather[c]与这个i合并
UNION(i,findfather(hobbyfather[c]));
//num[findfather(i)]++;
}
else{//这个hobby之前没有被提及
hobbyfather[c]=i;
//num[findfather(i)]++;
}
}
}
for(i=1;i<=n;i++){
num[findfather(i)]++;
}
sort(num+1,num+n+1,cmp);
for(i=1;i<=n;i++){
if(num[i]==0) break;
}
printf("%d\n",i-1);
for(j=1;j<i-1;j++){
printf("%d ",num[j]);
}
printf("%d",num[i-1]);
return 0;
}
找朋友:即找有相同的朋友的团体
#include<stdio.h>
int father[110];
int n;
void initial(){
int i;
for(i=1;i<=n;i++){
father[i]=i;
}
}
int findfather(int a){
int x=a;
while(a!=father[a]){
a=father[a];
}//a是x的根
//以下缩短路径
while(x!=father[x]){
int z=x;
father[x]=a;//该路径上的元素根都改为a
x=father[z];//寻找下一个
}
return a;
}
void UNION(int a,int b){//若a,b所在不同集合,合并
int fa=findfather(a);
int fb=findfather(b);
if(fa!=fb){
father[fa]=fb;//注意这里合并是根的合并
}
}
int main(){
int m,num=0,i;
scanf("%d %d",&n,&m);
initial();
for(i=0;i<m;i++){
int a,b;
scanf("%d %d",&a,&b);
UNION(a,b);
}
for(i=1;i<=n;i++){
if(father[i]==i) num++;
}
printf("%d",num);
return 0;
}
问题 A: 通信系统
时间限制: 1 Sec 内存限制: 32 MB提交: 152 解决: 51
[ 提交][ 状态][ TK题库][命题人: ]
题目描述
为了提高传送效率和节约资源,要求当消息在某个端点生成后,其余各个端点均能接收到消息,并且每个端点均不会重复收到消息。
现给你通信系统的描述,你能判断此系统是否符合以上要求吗?
输入
每组输入首先包含2个整数N和M,N(1<=N<=1000)表示端点个数,M(0<=M<=N*(N-1)/2)表示通信线路个数。
接下来M行每行输入2个整数A和B(1<=A,B<=N),表示端点A和B由一条通信线缆相连。两个端点之间至多由一条线缆直接相连,并且没有将某个端点与其自己相连的线缆。
当N和M都为0时,输入结束。
输出
样例输入
4 3
1 2
2 3
3 4
3 1
2 3
0 0
样例输出
Yes
No
#include<stdio.h>
int father[1010];
int n;
void initial(){
int i=0;
for(i=1;i<=n;i++){
father[i]=i;
}
}
int findfather(int a){
int x=a;
while(a!=father[a]){
a=father[a];
}
while(x!=father[a]){
int z=x;
x=father[x];
father[z]=a;
}
return a;
}
void UNION(int a,int b){
int fa=findfather(a);
int fb=findfather(b);
if(fa!=fb) father[fa]=fb;
}
int main(){
int i,m,num=0;
scanf("%d %d",&n,&m);
while(n!=0||m!=0){//这个判断条件要注意,不是&&,因为m可以为0
initial();//不仅不能忘记initial更不能忘记先scanf&n,再initial!!!
for(i=0;i<m;i++){
int a,b;
scanf("%d %d",&a,&b);
UNION(a,b);
}
for(i=1;i<=n;i++){
if(father[i]==i) num++;
}
if(num==1) printf("Yes\n");
else printf("No\n");
scanf("%d %d",&n,&m);
}
return 0;
}
问题 B: 畅通工程
时间限制: 1 Sec 内存限制: 32 MB提交: 61 解决: 35
[ 提交][ 状态][ TK题库][命题人: ]
题目描述
某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?
输入
测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。
注意:两个城市之间可以有多条道路相通,也就是说
3 3
1 2
1 2
2 1
这种输入也是合法的
当N为0时,输入结束,该用例不被处理。
输出
对每个测试用例,在1行里输出最少还需要建设的道路数目。
样例输入
5 3
1 2
3 2
4 5
0
样例输出
1
//有n个集合,就需要再建n-1条路
#include<stdio.h>
int father[1010];
int n;
void initial(){
int i;
for(i=1;i<=n;i++){
father[i]=i;
}
}
int findfather(int a){
int x=a;
while(a!=father[a]){
a=father[a];
}
while(x!=father[a]){
int z=x;
x=father[z];
father[z]=a;
}
return a;
}
void UNION(int a,int b){
int fa=findfather(a);
int fb=findfather(b);
if(fa!=fb) father[fa]=fb;
}
int main(){
int i,j,m;
scanf("%d %d",&n,&m);
while(n!=0){
initial();
int num=0;
for(j=0;j<m;j++){
int a,b;
scanf("%d %d",&a,&b);
UNION(a,b);
}
for(i=1;i<=n;i++){
if(father[i]==i) num++;
}
printf("%d\n",num-1);
scanf("%d %d",&n,&m);
}
return 0;
}