uva247

题目描述:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=20840

/* solution: 首先用floyd算法求出闭包,即g[i][j]表示i是否直接或者间接给j打过电话。 g[i][j] = g[j][i] = 1时二者处于同一个电话圈 date: 2016/2/25 */
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <string>

using namespace std;
const int maxn = 30;
const int maxLetter = 30;

int n, m;
int vis[maxn], d[maxn][maxn];
vector<string> names;

void floyd() {  //floyd算法求出闭包
    for(int k = 0; k < n; k++)
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                d[i][j] = d[i][j] || (d[i][k] && d[k][j]);
}

void dfs(int id) {
    vis[id] = 1;
    for(int i = 0; i < n; i++) {
        if(!vis[i] && d[id][i] && d[i][id]) {
            printf(", %s", names[i].c_str());
            dfs(i);
        }
    }
}

void print() {
    for(int i = 0; i < n; i++) {
        if(!vis[i]) {
            printf("%s", names[i].c_str());
            dfs(i);
            printf("\n");
        }
    }
}

int setID(string name) {
    for(int i = 0; i < names.size(); i++)   //如果找到,返回下标
        if(names[i] == name)    return i;
    names.push_back(name);  //如果尚未找到,压进vector中,返回下标
    return names.size() - 1;
}

int main()
{
   // freopen("input.txt", "r", stdin);
    int kase = 0;
    while(scanf("%d%d", &n, &m) == 2 && n) {
        memset(d, 0, sizeof(d));    //初始化
        memset(vis, 0, sizeof(vis));
        names.clear();

        char name1[maxLetter], name2[maxLetter];
        for(int i = 0; i < m; i++) {
            scanf("%s%s", name1, name2);
            d[setID(name1)][setID(name2)] = 1;
        }
        floyd();    //floyd算法求闭包

        if(kase > 0)    printf("\n");
        printf("Calling circles for data set %d:\n", ++kase);
        print();    //打印答案
    }
    return 0;
}

你可能感兴趣的:(算法,闭包)