题意:如果两个人互通电话,那么他们就在一个电话圈里,现在给定 n 个人,并且给定 m 个通话记录,让你输出所有的电话圈。
析:刚开始没想到是Floyd算法,后来才知道是这个算法,利用这个算法进行连通性的判定,当且仅当d[i][j] = d[j][i] = 1时,他们是在一个圈里。
然后用Floyd算法,把所有的关系都找到,最后再用DFS输出即可。通过这个题发现阶段不一样,那么写出来的东西也就不一样,这是第二次做这个题了,
第一次没用DFS,用的是set和map,来输出和记录。
代码如下:
第一次的
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <map> #include <string> #include <vector> #include <set> using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 30 + 5; map<string, int> mp; int d[30][30]; vector<int> G[maxn]; int main(){ // freopen("int.txt", "r", stdin); int n, m, cases = 0; while(scanf("%d %d", &n, &m)){ if(!m && !n) break; for(int i = 0; i < maxn; ++i) G[i].clear(); mp.clear(); string s1, s2; memset(d, 0, sizeof(d)); int indx = 1; for(int i = 0; i < m; ++i){ cin >> s1 >> s2; if(!mp.count(s1)) mp[s1] = indx++;//获得编号 if(!mp.count(s2)) mp[s2] = indx++; d[mp[s1]][mp[s2]] = 1; } for(int k = 1; k <= n; ++k)//Floyd算法判断连通性 for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) d[i][j] = d[i][j] || (d[i][k] && d[k][j]); set<int> sets; for(int i = 1; i <= n; ++i){ if(sets.count(i)) continue;//判断是不是已经放过了 G[i].push_back(i); sets.insert(i); for(int j = 1; j <= n; ++j) if(i != j && d[i][j] && d[j][i]){ G[i].push_back(j); sets.insert(j); } } if(cases) printf(" "); printf("Calling circles for data set %d: ", ++cases); for(int i = 1; i <= n; ++i){ if(!G[i].size()) continue; for(int j = 0; j < G[i].size(); ++j){ if(j) printf(", "); for(map<string, int> :: iterator it = mp.begin(); it != mp.end(); ++it)//遍历map if(it->second == G[i][j]){ cout << it->first; break; } } printf(" "); } } return 0; }
我都发现写的好差劲啊。。。。。
这是第二次的,还可以吧
#include <cstdio> #include <iostream> #include <algorithm> #include <map> #include <string> #include <cstring> #include <vector> using namespace std; const int maxn = 25 + 5; int cnt, n; int d[maxn][maxn], vis[maxn]; vector<string> name; int getid(const string &s){//记录编号 for(int i = 0; i < name.size(); ++i) if(name[i] == s) return i; name.push_back(s); return name.size()-1; } void dfs(int u){//递归输出 vis[u] = 1; for(int i = 0; i < n; ++i) if(!vis[i] && d[u][i] && d[i][u]){ cout << ", " << name[i]; dfs(i); } return ; } int main(){ // freopen("in.txt", "r", stdin); int m, kase = 0; while(scanf("%d %d", &n, &m) == 2 && n){ name.clear(); string s1, s2; memset(d, 0, sizeof(d)); memset(vis, 0, sizeof(vis)); while(m--){ cin >> s1 >> s2; int u = getid(s1); int v = getid(s2); d[u][v] = 1; } for(int k = 0; k < n; ++k)//Floyd算法判断连通性 for(int i = 0; i < n; ++i) for(int j = 0; j < n; ++j) d[i][j] |= d[i][k] && d[k][j]; if(kase) printf(" "); printf("Calling circles for data set %d: ", ++kase); for(int i = 0; i < n; ++i) if(!vis[i]){ cout << name[i]; dfs(i); cout << endl; } } return 0; }