UVa247 - Calling Circles ( floyed求传递闭包 )

题意

电话圈, 每行输出在一个圈内的人名

思路

有向图的传递闭包
该有向图中, 并不需要关心路径长度, 只需要关心两点之间是否有通路, 则可以用”1”和”0”表示”连通”和”不连通”. 这样只需要将floyed算法中的语句改为 d[i][j] = d[i][j]||(d[i][k]&&d[k][j]) 即可求得传递闭包

AC代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <set>
#include <vector>

using namespace std;
const int INF = 0x3f3f3f3f;
int n, m;
map<int, string> ID;
set<string> names;
const int maxn = 30;
int g[maxn][maxn];
int f[maxn];
vector<string> vec[maxn];

void init()
{
    if(!names.empty())  names.clear();
    if(!ID.empty())     ID.clear();
    for( int i = 0; i <= n; i++ )
        vec[i].clear();
    memset(g, 0, sizeof g);
    for(int i = 1; i <= n; i++)
        f[i] = i;
}

int find_(int a)
{
    if( f[a] != a ) f[a] = find_(f[a]);
    return f[a];
}

void union_(int a, int b)
{
    int aa = find_(a), bb = find_(b);
    if(aa!=bb)
    {
        f[bb] = aa;
    }
    return;
}

void floyed(){   // floyed 求传递闭包
    for(int k = 1; k <= n; k++)
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                g[i][j] = g[i][j] || (g[i][k] && g[k][j]);
}

int findid(string a){
    map<int, string>::iterator it = ID.begin();
    for(;it!=ID.end();it++){
        if( it->second == a )
            return it->first;
    }
}

int main()
{
    string stra, strb;
    int cnt;
    int num = 0;
    while( cin >> n >> m && n && m ){
        cnt = 0;
        init();
        for(int i = 0; i < m; i++){
            cin >> stra >> strb;
            if(!names.count(stra)){ ID[++cnt] = stra; names.insert(stra); }
            if(!names.count(strb)){ ID[++cnt] = strb; names.insert(strb); }
            g[findid(stra)][findid(strb)] = 1;
        }
        floyed();
        printf("Calling circles for data set %d:\n", ++num);
        for(int i = 1 ; i <= n; i++ ){
            for(int j = i+1; j <= n; j++){
                if( g[i][j] == 1 && g[j][i] == 1 ){
                    union_(i, j);
                }
            }
        }
        for(int i = 1; i <= n; i++)
        {
            vec[f[i]].push_back(ID[i]);
        }
        for(int i = 1; i <= n; i++){
            if( vec[i].size() == 0 ) continue;
            for(int j = 0; j < (int)vec[i].size(); j++){
                if( j != 0 ) cout << ", ";
                cout << vec[i][j];
            }
            cout << "\n";
        }
    }
    return 0;
}
posted @ 2018-07-23 13:29  JinxiSui  阅读(157)  评论(0编辑  收藏  举报