UVa - 247 Calling Circles(Floyd - TC)

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

#include <iostream>
#include <string>
#include <cstring>
#include <map>
#include <vector>

using namespace std;
/***************************************************************************************************************
        题意:A打给B,B打给A,那么AB就构成了一个电话圈。如果A->B,B->C,C->A,那么这也构成了电话圈,
            值得一提的是,如果这种情况下,C->D,D->C,那么D也算是在电话圈内。输出所有的电话圈中的人。
        思路:
        1,学习了 floyd 的 TC ,可以判断两个点是否在一个圈内(利用floyd求出有向图的传递闭包)
            a,初始化相关的两个结点  d[i][j] = 1;
            b,d[i][j] = min (d[i][j],d[i][k] + d[k][j]) 改成 d[i][j] = d[i][j] || (d[i][k] && d[k][j])
            c,判断依据: d[i][j] == d[j][i] == 1
        2,根据传递闭包关系构造新图,输出连通分量中的所有结点

        核心:Floyd - TC
**************************************************************************************************************/
int dist[30][30];       //标志两个人是否在同一个圈
int visit[30];

map<string, int> IDcache;       // 姓名 -> 编号
string name[30];                // 编号 -> 姓名
int num;
vector <string> ans[30];

//vector<string> name;              这里本来想这么存名字和最后输出的电话圈的,但是push_back老是用不对
//vector<vector<string> > ans;      于是改成上面的,string name[]存名字,vector<string> 存电话圈的人

int ID(string s){
    if(IDcache.count(s))    return IDcache[s];
    name[++num] = s;
    return IDcache[s] = num;
}

int main()
{
    int n,m;
    int cnt = 0;
    while(cin>>n>>m && n && m){
        num = 0;                                         //一定要初始化
        IDcache.clear();                                 //一定要初始化
        for(int i = 0;i <= n;i ++)  ans[i].clear();      //一定要初始化

        string s1,s2;
        memset(dist,0,sizeof(dist));
        for(int i = 1;i <= m;i ++){
            cin>>s1>>s2;
            int id1 = ID(s1),id2 = ID(s2);
            dist[id1][id2] = 1;     //相关即为1
        }

        for(int k = 1;k <= n;k ++)
            for(int i = 1;i <= n;i ++)
                for(int j = 1;j <= n;j ++)
                    dist[i][j] = dist[i][j] || (dist[i][k] && dist[k][j]);      //Floyd的传递闭包(TC)

        memset(visit,0,sizeof(visit));
        int len = 0;
        for(int i = 1;i <= n;i ++){
            if(!visit[i]){
                visit[i] = 1;
                for(int j = 1;j <= n;j ++){
                    if(visit[j])    continue;
                    if(dist[i][j] && dist[i][j] == dist[j][i]){
                        ans[len].push_back(name[j]);
                        visit[j] = 1;
                    }
                }
                ans[len++].push_back(name[i]);
            }
        }

        if(cnt)
            cout<<endl;
        cout<<"Calling circles for data set "<<++cnt<<":"<<endl;
        for(int i = 0;i < len;i ++){
            for(int j = 0;j < ans[i].size();j ++){
                if(j)  cout<<", ";
                cout<<ans[i][j];
            }
            cout<<endl;
        }
    }
    return 0;
}



 

posted on 2016-05-27 12:09  Jstyle  阅读(107)  评论(0编辑  收藏  举报

导航