Calling Circles

Description:

If you‘ve seen television commercials for long-distance phone companies lately, you‘ve noticed that many companies have been spending a lot of money trying to convince people that they provide the best service at the lowest cost.
One company has ``calling circles." You provide a list of people that you call most frequently. If you call someone in your calling circle (who is also a customer of the same company), you get bigger discounts than if you call outside your circle. Another
company points out that you only get the big discounts for people in your calling circle, and if you change who you call most frequently, it‘s up to you to add them to your calling circle.

LibertyBell Phone Co. is a new company that thinks they have the calling plan that can put other companies out of business. LibertyBell has calling circles, but they figure out your calling circle for you. This is how it works.
LibertyBell keeps track of all phone calls. In addition to yourself, your calling circle consists of all people whom you call and who call you, either directly or indirectly.

For example, if Ben calls Alexander, Alexander calls Dolly, and Dolly calls Ben, they are all within the same circle. If Dolly also calls Benedict and Benedict calls Dolly, then Benedict is in the same calling circle as Dolly,
Ben, and Alexander. Finally, if Alexander calls Aaron but Aaron doesn‘t call Alexander, Ben, Dolly, or Benedict, then Aaron is not in the circle.

You‘ve been hired by LibertyBell to write the program to determine calling circles given a log of phone calls between people.

Input

The input file will contain one or more data sets. Each data set begins with a line containing two integers,
n and m. The first integer, n, represents the number of different people who are in the data set. The maximum value for
n is 25. The remainder of the data set consists of m lines, each representing a phone call. Each call is represented by two names, separated by a single space. Names are first names only (unique within a data set), are case sensitive, and
consist of only alphabetic characters; no name is longer than 25 letters.

For example, if Ben called Dolly, it would be represented in the data file as

Ben Dolly

Input is terminated by values of zero (0) for
n
and m.

Output

For each input set, print a header line with the data set number, followed by a line for each calling circle in that data set. Each calling circle line contains the names of all the people in any order within the circle, separated
by comma-space (a comma followed by a space). Output sets are separated by blank lines.

Sample Input

5 6
Ben Alexander
Alexander Dolly
Dolly Ben
Dolly Benedict
Benedict Dolly
Alexander Aaron
14 34
John Aaron
Aaron Benedict
Betsy John
Betsy Ringo
Ringo Dolly
Benedict Paul
John Betsy
John Aaron
Benedict George
Dolly Ringo
Paul Martha
George Ben
Alexander George
Betsy Ringo
Alexander Stephen
Martha Stephen
Benedict Alexander
Stephen Paul
Betsy Ringo
Quincy Martha
Ben Patrick
Betsy Ringo
Patrick Stephen
Paul Alexander
Patrick Ben
Stephen Quincy
Ringo Betsy
Betsy Benedict
Betsy Benedict
Betsy Benedict
Betsy Benedict
Betsy Benedict
Betsy Benedict
Quincy Martha
0 0

Sample Output

Calling circles for data set 1:
Ben, Alexander, Dolly, Benedict
Aaron

Calling circles for data set 2:
John, Betsy, Ringo, Dolly
Aaron
Benedict
Paul, George, Martha, Ben, Alexander, Stephen, Quincy, Patrick

# include <cstdio>
# include <vector>
# include <cstring>
# include <iostream>
using namespace std;

vector < string > name;
int d[30][30],vis[30],n,m;

int ID(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 search(int i)
{
    vis[i]=1;
    for(int j=0;j<n;j++)
        if(d[i][j]&&!vis[j]&&d[j][i])
        {
            printf(", %s",name[j].c_str());
            search(j);
        }
}

int main()
{
    int kase=0;
    char c[99],s[99];
    while(~scanf("%d%d",&n,&m)&&n&&m)
    {
        int i,j,k;
        name.clear();
        memset(d,0,sizeof(d));
        memset(vis,0,sizeof(vis));
        for(i=0;i<n;i++)   d[i][i]=1;

        for(i=0;i<m;i++)
        {
            scanf("%s%s",c,s);
            d[ID(c)][ID(s)]=1;
        }

        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][k] && d[k][j];

        if(kase>0 )    printf("\n");

        printf("Calling circles for data set %d:\n",++kase);

        for(i=0;i<name.size();i++)
        {
            if(!vis[i])
            {
                printf("%s",name[i].c_str());
                search(i);
                printf("\n");
            }
        }
    }
    return 0;
}
时间: 2024-10-18 08:18:43

Calling Circles的相关文章

11.3.4 例题11-4 UVA 247 Calling Circles (有向图的传递闭包)

题目大意: 给你n个人,m条边,a->b,b->a,才能说这两个人是联通的.问现在有多少个联通圈.输出每个联通圈.n<=25 解题思路: 直接建图,用有向图的闭包传递特性来处理每个人之间的联通关系.然后dfs一次,遍历邻接矩阵中与某个点相连的几个点,边遍历, 边打印输出. 代码: # include<cstdio> # include<iostream> # include<map> # include<cstring> # include

--uva247(calling circles)强联通与floyd-warshell

图论题:一开始我是用tarjan算法做的,wrong answer 了很多次,然后又用了floyd-warshell算法,也wa了 最后找了题解,原来最后的dataset后面不是组数,是样例的编号,题根本就没说,让人怎么理解... tarjan #include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<map> #include<alg

【UVA】247 - Calling Circles(floyd判断包闭,dfs输出)

最近状态不佳,总是爱犯低级错误,比较水的题,没什么需要讲得,要说的可能是floyd判断包闭吧 void Floyd() { for(int k=1; k<=n; k++) for(int i=1; i<=n; i++) if(map[i][k]) for(int j=1; j<=n; j++) if(map[k][j]) map[i][j] = 1; } 之前做了不少图论,图论周感觉能应付的过去. 14059727 247 Calling Circles Accepted C++ 0.0

247 - Calling Circles (Floyd 求传递闭包)

该题恰好用到刚刚讲到的Floyd求传递闭包 , 因为该题的数据量不是很大, 要是大了估计就要用其他方法了 .  但是这毕竟是一个很简单易写的算法 . 求出传递闭包之后就用并查集将在一个电话圈的人合并在一起,最后输出 . 细节参见代码: #include<bits/stdc++.h> using namespace std; int n,m,d[30][30],par[30],kase = 0; string s1,s2; map<string , int > p; map<i

uva 247 Calling Circles(Floyd 的简单应用)

最近在看图论的经典算法, 先看的是求单源最短路的dijkstra,优化后的算法用了优先队列,看起来有点复杂. 感觉 弗洛伊德(Floyd) 要比 迪克斯特拉(dijkstra) 更好理解一点,但是Floyd是三层循环,当然会慢很多.一旦数据开大就跪了吧. floyd可以用来求 两个 连通点间的最短路问题.同时可以得到边权的和,即最短路的长度. 另外一个比较简单的应用,还可以用来判断两点间的连通性.即判断两点是否连通.本题就是弗洛伊德的这种简单用法. #include<cstdio> #incl

UVa247 Calling Circles (Floyd,DFS)

链接:http://bak3.vjudge.net/problem/UVA-247 分析:先用Floyd求出有向图的传递闭包,然后用DFS求出各个联通分量即可. 1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <string> 5 using namespace std; 6 7 vector<string> names; 8 int ID(const

UVa 247 Calling Circles【传递闭包】

题意:给出n个人的m次电话,问最后构成多少个环,找出所有的环 自己想的是:用map来储存人名,每个人名映射成一个数字编号,再用并查集,求出有多少块连通块,输出 可是map不熟,写不出来,而且用并查集输出的时候感觉貌似很麻烦 然后再用的传递闭包,可是判断到d[i][j]==1和d[j][i]==1,该怎么输出路径呢 于是看了lrj的代码= = 用的是一个ID(string s)函数来给名字编号,和第五章的集合栈计算机那题的办法一样 然后用dfs输出路径= =(这个要好好--好好--好好学) 最后还

UVa 247 (传递闭包) Calling Circles

题意: 有n个人m通电话,如果有两个人相互打电话(直接或间接)则在同一个电话圈里.输出所有电话圈的人的名单. 分析: 根据打电话的关系,可以建一个有向图,然后用Warshall算法求传递闭包. 最后输出是辅助一个标记数组,用DFS输出的,这个办法挺巧妙的. 本来我原来的想法是,用并查集求所有的连通分量,然后再好多次循环找连通分量一致的名字输出,那样太麻烦了. ios::sync_with_stdio(false);这个最好不要随便用,可能会产生某些副作用. 字符指针是可以传给string对象作参

UVa 247 - Calling Circles(Floyd求有向图的传递闭包)

链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=183 题意: 如果两个人相互打电话(直接或间接),则说他们在同一个电话圈里.例如,a打给b,b打给c,c打给d,d打给a,则这4个人在同一个圈里:如果e打给f但f不打给e,则不能推出e和f在同一个电话圈里.输入n(n≤25)个人的m次电话,找出所有电话圈.人名只包含字母,不超过25个