UVa 247 电话圈(Floyd传递闭包)
https://vjudge.net/problem/UVA-247
题意:
如果两个人相互打电话,则说他们在同一个电话圈里。例如,a打给b,b打给c,c打给d,d打给a,则这4个人在同一个圈里;如果e打给f但f不打给e,则不能推出e和f在同一个电话圈里,输出所有电话圈。
思路:
通过Floyd求一个传递闭包。最后dfs输出每一个电话圈即可。
传递闭包的求法:
1 for (int k = 0; k < n;k++) 2 for (int i = 0; i < n;i++) 3 for (int j = 0; j < n; j++) 4 d[i][j] = d[i][j] || (d[i][k] && d[k][j]);
1 #include<iostream> 2 #include<cstring> 3 #include<string> 4 #include<algorithm> 5 #include<map> 6 #include<vector> 7 using namespace std; 8 9 int n, m; 10 int d[30][30]; 11 string s1, s2; 12 map<string, int> ID; 13 vector<string> name; 14 int vis[30]; 15 16 void dfs(int k) 17 { 18 vis[k] = 1; 19 for (int i = 0; i < n; i++) 20 { 21 if (d[k][i] && d[i][k]) 22 { 23 if (!vis[i]) 24 { 25 cout << ", " << name[i]; 26 dfs(i); 27 } 28 } 29 } 30 } 31 32 int main() 33 { 34 //freopen("D:\\txt.txt", "r", stdin); 35 int kase = 1; 36 while (scanf("%d%d", &n, &m)) 37 { 38 if (n == 0 && m == 0) break; 39 if (kase > 1) printf("\n"); 40 memset(d, 0, sizeof(d)); 41 memset(vis, 0, sizeof(vis)); 42 ID.clear(); 43 name.clear(); 44 int cnt = 0; 45 for (int i = 0; i < m; i++) 46 { 47 cin >> s1 >> s2; 48 if (!ID.count(s1)) 49 { 50 ID[s1] = cnt++; 51 name.push_back(s1); 52 } 53 if (!ID.count(s2)) 54 { 55 ID[s2] = cnt++; 56 name.push_back(s2); 57 } 58 int x = ID[s1]; 59 int y = ID[s2]; 60 d[x][y] = 1; 61 } 62 63 for (int k = 0; k < n;k++) 64 for (int i = 0; i < n;i++) 65 for (int j = 0; j < n; j++) 66 d[i][j] = d[i][j] || (d[i][k] && d[k][j]); 67 68 printf("Calling circles for data set %d:\n", kase++); 69 for (int i = 0; i < n; i++) 70 { 71 if (!vis[i]) 72 { 73 cout << name[i]; 74 dfs(i); 75 printf("\n"); 76 } 77 } 78 } 79 return 0; 80 }