UVa 247 Calling Circles (DFS+Floyd)

题意:如果两个人互通电话,那么他们就在一个电话圈里,现在给定 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;
}
原文地址:https://www.cnblogs.com/dwtfukgv/p/5605124.html