• 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;
    }
    
  • 相关阅读:
    Codeforces 735C:Tennis Championship(数学+贪心)
    HDU 5934:Bomb(强连通缩点)
    BZOJ-2743 采花
    BZOJ-1878 HH的项链
    BZOJ-1798 维护序列
    BZOJ-1911 特别行动队
    BZOJ-1010 玩具装箱
    BZOJ-1096 仓库建设
    BZOJ-1012 最大数
    ZOJ 3696 Alien's Organ(泊松定理,期望值)
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/5605124.html
Copyright © 2020-2023  润新知