Topic: If two people call each other (directly or indirectly), they say they are in the same telephone circle. For example, if a calls b, B calls c, C calls d and d calls a, then the four people are in the same circle; if e calls F and f does not call e, then E and F can not b e launched in the same circle. Enter m calls from n (n<=25) individuals and find out all the rings. Names contain only letters, not more than 25 characters, and do not repeat.
solution_1:tarjan Finds Directed Graph SCC
#include <map>
#include <stack>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 50;
vector<int> G[N];
stack<int> S;
int dfn[N], low[N];
bool bl[N];
int id;
map<string,int> mp1;
map<int,string> mp2;
int tot=0;
int Hash(string str){
if( mp1.count(str) ) return mp1[str];
mp1[str]=++tot;
mp2[tot]=str;
return tot;
}
void dfs(int u){
dfn[u]=low[u]=++id;
S.push(u);
bl[u]=true;
for ( int i=0; i<G[u].size(); i++ ){
int v=G[u][i];
if( !dfn[v] ) {
dfs(v);
low[u]=min(low[u],low[v]);
} else if( bl[v] ){
low[u]=min(low[u],dfn[v]);
}
}
if( low[u]==dfn[u] ){
int ok=0;
while( !S.empty()){
int x=S.top(); S.pop();
bl[x]=false;
if( !ok ) cout<<mp2[x], ok=1;
else cout<<", "<<mp2[x];
if( x==u ) {
break;
}
}
cout<<"\n";
}
}
void find_scc(int n){
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(bl,0,sizeof(bl));
id=0;
for ( int i=1; i<=n; i++ )
if( !dfn[i] ) dfs(i);
}
int n, m;
int main(){
int k=0;
while( ~scanf("%d%d", &n, &m ) && (n||m) ){
if( k ) cout<<"\n";
printf("Calling circles for data set %d:\n", ++k);
for ( int i=0; i<N; i++ ) G[i].clear();
tot=0;
mp1.clear(); mp2.clear();
for ( int i=1; i<=m; i++ ){
string s1,s2;
cin>>s1>>s2;
int x=Hash(s1), y=Hash(s2);
G[x].push_back(y);
}
find_scc(n);
}
}
solution_2: Floyed for transitive closure
#include <map>
#include <stack>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 30;
int a[N][N];
bool vis[N];
map<string,int> mp1;
map<int,string> mp2;
int tot=0;
int Hash(string str){
if( mp1.count(str) ) return mp1[str];
mp1[str]=++tot;
mp2[tot]=str;
return tot;
}
int n, m;
int main(){
int k=0;
while( ~scanf("%d%d", &n, &m ) && (n||m) ){
if( k ) cout<<"\n";
printf("Calling circles for data set %d:\n", ++k);
memset(a,0,sizeof(a));
memset(vis,0,sizeof(vis));
tot=0;
mp1.clear(); mp2.clear();
for ( int i=1; i<=m; i++ ){
string s1,s2;
cin>>s1>>s2;
int x=Hash(s1), y=Hash(s2);
a[x][y]=1;
}
for ( int k=1; k<=n; k++ )
for ( int i=1; i<=n; i++ )
for ( int j=1; j<=n; j++ )
a[i][j]=a[i][j] || (a[i][k]&&a[k][j]);
for ( int i=1; i<=n; i++ ){
if( vis[i] ) continue;
vis[i]=1;
cout<<mp2[i];
for ( int j=1; j<=n; j++ )
if( !vis[j] && a[i][j] && a[j][i] ) {
vis[j]=1;
cout<<", "<<mp2[j];
}
cout<<"\n";
}
}
}