Calling Circles UVA - 247
题意:
给你一个有向图,让你求有多少个强连通分量。
思路1:
- 先floyd传递闭包。
- 之后根据上面的关系,开始连边 当且仅当 u->v, 且 v->u。(即u可以到达v。v可以到达u)
- 之后就是跑dfs,求联通块。
AC
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#define mst(x,a) memset(x,a,sizeof(x))
#define For(i,x,y) for(int i=(x); i<=(y); i++)
#define fori(i,x,y) for(int i=(x); i<(y); i++)
#define pb push_back
using namespace std;
map<string,int>cach;
vector<string>name;
vector<int>g[50];
int id(string s){
if(cach.count(s))return cach[s];
name.pb(s);
return cach[s]=name.size()-1;
}
int n,m;
int d[50][50],vis[50];
void init(){
fori(i,0,n)g[i].clear();
cach.clear();
name.clear();
mst(vis,0);
fori(i,0,n){
fori(j,0,n){
if(i==j)d[i][j]=1;
else d[i][j]=0;
}
}
string s1,s2;
int u,v;
For(i,1,m){
cin>>s1>>s2;
u=id(s1);v=id(s2);
d[u][v]=1;//g[u].pb(v);
}
}
void dfs(int u){
vis[u]=1;
fori(i,0,g[u].size()){
int v=g[u][i];
if(!vis[v]){
cout<<", "<<name[v];
dfs(v);
}
}
}//, Be
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int kase=0;
while(cin>>n>>m,n||m){
if(kase)cout<<endl;
init();
///传递闭包
fori(k,0,n)fori(i,0,n)fori(j,0,n)d[i][j]=d[i][j]||(d[i][k]&&d[k][j]);
///连通就连边。
fori(i,0,n)fori(j,0,n)if(d[i][j]&&d[j][i]&&i!=j)g[i].pb(j);
cout<<"Calling circles for data set "<<++kase<<":"<<endl;
fori(i,0,n){
if(vis[i]==0){
cout<<name[i];
dfs(i);
cout<<endl;
}
}
// cout<<endl;
}
return 0;
}
思路2:
- tarjan的有向图求强连通分量的模板题。
- 求完之后,把每个连通分量输出即可。
AC
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <stack>
#define For(i,x,y) for(int i=(x); i<=(y); i++)
#define fori(i,x,y) for(int i=(x); i<(y); i++)
#define mst(x,a) memset(x,a,sizeof(x))
#define pb push_back
using namespace std;
const int maxn=50;
stack<int>s;
vector<int>g[maxn],scc[maxn];
int dfn[maxn],low[maxn],sccno[maxn],dfs_clock,scc_cnt;
void tarjan(int u){
dfn[u] = low[u] = ++dfs_clock;
s.push(u);
fori(i,0,g[u].size()){
int v = g[u][i];
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}else if(!sccno[v])low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u]){
scc_cnt++;
int x;
do{
x = s.top();s.pop();
sccno[x] = scc_cnt;
scc[scc_cnt].pb(x);
}while(x!=u);
}
}
map<string,int>cach;
vector<string>name;
int id(string s){
if(cach.count(s))return cach[s];
name.pb(s);
return cach[s]=name.size()-1;
}
int n,m;
void init(){
mst(low,0);mst(dfn,0);mst(sccno,0);
dfs_clock=scc_cnt=0;
fori(i,0,n)g[i].clear();
For(i,1,n)scc[i].clear();
cach.clear();
name.clear();
string s1,s2;
int u,v;
fori(i,0,m){
cin>>s1>>s2;
u=id(s1),v=id(s2);
g[u].pb(v);
}
}
int main()
{
int kase=0;
while(cin>>n>>m,n||m){
if(kase)cout<<endl;
init();
fori(u,0,n)if(!dfn[u])tarjan(u);
cout<<"Calling circles for data set "<<++kase<<":"<<endl;
For(i,1,scc_cnt){
int id=scc[i][0];
cout<<name[id];
fori(j,1,scc[i].size()){
id = scc[i][j];
cout<<", "<<name[id];
}
cout<<endl;
}
}
return 0;
}