/*
来自算法竞赛入门经典刘汝佳p364
把Floyd中的"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])"通过这样来求有向图的传递闭包
*/
#include<iostream>
#include <stdio.h>
#include <string>
#include <string.h>
#include <vector>
#define MAXN 36
using namespace std;
vector<string> name;
int n;
int mmp[MAXN][MAXN];
bool book[MAXN];
int getid(string x)
{//新学到的一招,把string变成代号的方法
for (int i = 0; i < name.size(); i++)
if (name[i] == x)return i;
name.push_back(x);
return name.size() - 1;
}
void dfs(int id)
{//对传递闭包遍历
book[id] = true;
for (int i = 0; i < n; i++)
if (!book[i] && mmp[id][i] && mmp[i][id])
{//如果满足它没有被访问过并且它在闭包里打印它
//在闭包里的意思就是mmp[i][j] == mmp[j][i]
cout << ", " << name[i];
dfs(i);
}
}
int main(void)
{
int m, k = 0;
while (scanf_s("%d%d", &n, &m) != EOF&&n+m)
{
if (k > 0)putchar('\n');
printf("Calling circles for data set %d:\n", ++k);
memset(mmp, 0, sizeof(mmp));
memset(book, 0, sizeof(book));
name.clear();//数据初始化
for (int i = 0; i < m; i++)
{
string name1, name2;
cin >> name1 >> name2;
mmp[getid(name1)][getid(name2)] = 1;
}
for (int k = 0; k < n; k++)
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)//Flody求传递闭包
mmp[i][j] = mmp[i][j] || (mmp[i][k] && mmp[k][j]);
for (int i = 0; i < n; i++)
{//对每一个数进行遍历
if (!book[i])
{//倘若它没有被打印过那就进入深搜
cout << name[i];
dfs(i);
putchar('\n');
}
}
}
return 0;
}