简单的板子题,就是字符串操作有点难啊啊啊,
要熟悉下离散图论里连通图(有向图)里的可达性矩阵Warshall算法,(有向图的传递闭包)
如果d[i][j]&&d[j][i]都联通,则双方可达,
此题就用一个map和string数组存储输入的字符串,flag数组标记;
代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<map>
typedef long long ll;
const int maxn=1010;
const int inf=0x3f3f3f;
using namespace std;
int d[maxn][maxn];
int flag[maxn];
map<string,int> mp;
int n,m;
string name[maxn];
int sum;
string s1,s2;
void in()
{
mp.clear();
memset(flag,0,sizeof(flag));
memset(d,0,sizeof(d));
sum=0;
}
int x,y;
void enter()
{
for(int i=1; i<=m; i++)
{
cin>>s1>>s2;
if(mp.count(s1))
{
//cout<<"if"<<":1"<<endl;
x=mp[s1];
}
else
{
//cout<<"else"<<":1"<<endl;
mp[s1]=++sum;
name[sum]=s1;
x=sum;
}
if(mp.count(s2))
{
//cout<<"if"<<":2"<<endl;
y=mp[s2];
}
else
{
//cout<<"else"<<":2"<<endl;
mp[s2]=++sum;
name[sum]=s2;
y=sum;
}
//cout<<x<<" "<<y<<endl;
d[x][y]=1;
}
}
void floyd()
{
for(int k=1; k<=m; k++)
for(int i=1; i<=m; i++)
for(int j=1; j<=m; j++)
if(d[i][j]<inf&&d[j][k]<inf)
d[i][j]=d[i][j]||(d[k][j]&&d[i][k]);
}
int main()
{
int t=1;
while(cin>>n>>m&&n+m)
{
if(t!=1) printf("
");
in();
enter();
//for(map<string,int>::iterator it=mp.begin();it!=mp.end();it++)
//cout<<it->first<<" "<<it->second<<endl;
floyd();
printf("Calling circles for data set %d:
",t++);
for(int i=1; i<=n; i++)
{
if(flag[i]) continue;
cout<<name[i];
for(int j=i+1; j<=n; j++)
{
if(flag[j]) continue;
if(d[i][j]&&d[j][i])
{
flag[j]=1;
cout << ", " <<name[j];
}
}
cout<<endl;
}
}
}