题目比较简单,但作为长久不写题之后的热身题还是不错的。
统计每组朋友的朋友圈的大小。
如果a和b是朋友,这个朋友圈的大小为2,如果b和c也是朋友,那么a和c也是朋友,此时这个朋友圈的大小为3。
输入t,表示接下来有t组数据。
每组数据有n组朋友关系。
接下来n行,每行一组朋友关系,然后输出这组朋友的朋友圈大小,即有多少朋友。
然后又是t组数据……(这点好坑)重复上述输入,直到数据结束。
因为最多有10^5个人,那么如果用线性字符串数组保存人名,肯定超时得不要不要的,所以要用map(每次操作时间复杂度为log2(n))。
据说如果并查集不压缩也会爆。我没试,诸位可以试一下。
废话说完,上代码
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 #include <map> 6 #include <string> 7 using namespace std; 8 9 map<string, int> mp; //字符串与数字转换 10 int val[100010]; //朋友数 11 int mg[100010]; //并查集使用的数组 12 int n, t; 13 14 int find(int x) 15 { 16 int fx = x; 17 while(mg[fx] != fx) fx = mg[fx]; 18 while(mg[x] != x) 19 { 20 int mid = mg[x]; 21 mg[x] = fx; 22 x = mid; 23 } 24 //printf("%5d ", fx); 25 return fx; 26 } 27 28 void merge(int x, int y) 29 { 30 int mx = find(x); 31 int my = find(y); 32 if(mx != my) 33 { 34 val[mx] += val[my]; 35 val[my] = val[mx]; 36 mg[mx] = my; 37 38 } 39 printf("%d ", val[mx]); 40 } 41 42 int main() 43 { 44 // freopen("test.txt", "r", stdin); 45 while(~scanf("%d", &t)) 46 { 47 while(t--) 48 { 49 scanf("%d", &n); 50 for(int i = 0; i < 100010; i++) 51 { 52 val[i] = 1; 53 mg[i] = i; 54 } 55 char a[25], b[25]; 56 int ans = 1; //因为map中int初始值为0,所以赋值时应从1开始 57 mp.clear(); //每次注意清空mp 58 for(int i = 0; i < n; i++) 59 { 60 scanf("%s%s", a, b); 61 if(!mp[a]) mp[a] = ans++; //加入新节点 62 if(!mp[b]) mp[b] = ans++; 63 merge(mp[a], mp[b]); 64 } 65 } 66 } 67 return 0; 68 }