题目描述 Description
cc是个超级帅哥,口才又好,rp极高(这句话似乎降rp),又非常的幽默,所以很多mm都跟他关系不错。然而,最关键的是,cc能够很好的调解各各妹妹间的关系。mm之间的关系及其复杂,cc必须严格掌握她们之间的朋友关系,好一起约她们出去,cc要是和不是朋友的两个mm出去玩,后果不堪设想……
cc只掌握着一些mm之间的关系,但是cc比较聪明,他知道a和b是朋友,b和c 是朋友,那么a和c也是朋友。
下面给出m对朋友关系, cc 定了p次约会,每次约会找两个mm,如果这两个mm是朋友,那么不会出乱子,输出‘safe',要是不是朋友,那么cc必然会挨……,输出‘cc cry'
输入描述 Input Description
第一行为n,m,p。n为mm的数量,cc知道m对朋友关系,有p次约会。
2到n+1 行,每行一个字符串,为第i个mm的名字。{字符串长度<=11,且全大写}
以下m行,每行两个字符串,用空格隔开 ,为有朋友关系的两个mm的名字。
以下p行,每行为两个字符串,用空格隔开,为这p次约会中两个mm的名字。
{保证数据不会出现没有出现过的名字}
输出描述 Output Description
输出P行表示第i次约会的情况,输出‘safe'或者‘cc cry'
样例输入 Sample Input
3 1 1
AAA
BBB
CCC
AAA CCC
AAA BBB
样例输出 Sample Output
cc cry
数据范围及提示 Data Size & Hint
0<m<=2008
0<p<=2008
题目分析:典型的并查集。
1 #include<stdio.h> 2 #include<string.h> 3 int n,m,p; 4 char name[2010][15]; 5 6 int pre[2010];//用于并查集的前驱数组 7 void make_set(int pre[]); 8 int Find(int x); 9 void mix(int x,int y); 10 11 int getStuID(char stuName[]);//传入某个学生的名字,返回学生的ID(名字在name[]中的下标) 12 13 int main() 14 { 15 int i; 16 char t1[15],t2[15]; 17 int a,b; 18 freopen("data.in","r",stdin); 19 20 scanf("%d%d%d",&n,&m,&p); 21 make_set(pre);//并查集数组pre[]的初始化 22 for(i=0;i<n;i++) scanf("%s",name[i]);//输入n个人的名字 23 for(i=0;i<m;i++)//输入m个关系 24 { 25 scanf("%s%s",t1,t2); 26 a=getStuID(t1); 27 b=getStuID(t2); 28 mix(a,b); 29 } 30 for(i=0;i<p;i++)//做p次问询 31 { 32 scanf("%s%s",t1,t2); 33 a=getStuID(t1); 34 b=getStuID(t2); 35 a=Find(a); 36 b=Find(b); 37 if(a!=b) printf("cc cry\n"); 38 else printf("safe\n"); 39 } 40 return 0; 41 } 42 void make_set(int pre[]) 43 { 44 int i; 45 for(i=0;i<n;i++) 46 pre[i]=i; 47 } 48 int Find(int x) 49 { 50 int r=x; 51 while(r!=pre[r]) 52 r=pre[r]; 53 54 int i=x,j; 55 while(pre[i]!=r) 56 { 57 j=pre[i]; 58 pre[i]=r; 59 i=j; 60 } 61 return r; 62 } 63 void mix(int x,int y) 64 { 65 int fx=Find(x),fy=Find(y); 66 if(fx!=fy) 67 { 68 pre[fy]=fx; 69 } 70 } 71 72 int getStuID(char stuName[])//传入某个学生的名字,返回学生的ID(名字在name[]中的下标) 73 { 74 int i=-1; 75 for(i=0;i<n;i++) 76 { 77 if(strcmp(stuName,name[i])==0) return i; 78 } 79 return i; 80 }