点这里 |
---|
题意: 判断一个有向图G是不是强连通图。
题解: Kosaraju算法、Tarjan算法。
Kosaraju
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
int n, m, u, v;
int cnt, vis[N], scc[N];
vector<int> G[N], rG[N];
vector<int> S;
void dfs1(int u){
vis[u] = 1;
for(int i = 0; i < G[u].size(); i++) if(!vis[G[u][i]]) dfs1(G[u][i]);
S.push_back(u);
}
void dfs2(int u){
scc[u] = cnt;
for(int i = 0; i < rG[u].size(); i++) if(!scc[rG[u][i]]) dfs2(rG[u][i]);
}
void kosaraju(){
cnt = 0;
S.clear();
for(int i = 1; i <= n; i++) vis[i] = scc[i] = 0;
for(int i = 1; i <= n; i++) if(!vis[i]) dfs1(i);
for(int i = n - 1; i >= 0; i--) if(!scc[S[i]]) {cnt++; dfs2(S[i]);}
}
int main(){
while(~scanf("%d%d", &n, &m) && n + m){
for(int i = 0; i <= n; i++) G[i].clear(), rG[i].clear();
while(m--){
scanf("%d%d", &u, &v);
G[u].push_back(v), rG[v].push_back(u);
}
kosaraju();
printf("%s\n", cnt == 1 ? "Yes" : "No");
}
return 0;
}
Tarjan
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
int n, m, u, v;
int cnt, dfn, top;
int num[N], low[N];
int scc[N], sta[N];
vector<int> G[N];
void dfs(int u){
sta[top++] = u;
num[u] = low[u] = ++dfn;
for(int i = 0; i < G[u].size(); i++){
int v = G[u][i];
if(!num[v]){
dfs(v);
low[u] = min(low[u], low[v]);
}
else if(!scc[v])
low[u] = min(low[u], num[v]);
}
if(low[u] == num[u]){
cnt++;
while(1){
int v = sta[--top];
scc[v] = cnt;
if(u == v) break;
}
}
}
void tarjan(){
cnt = dfn = top = 0;
for(int i = 0; i <= n; i++) num[i] = low[i] = scc[i] = 0;
for(int i = 1; i <= n; i++) if(!num[i]) dfs(i);
}
int main(){
while(~scanf("%d%d", &n, &m) && n + m){
for(int i = 1; i <= n; i++) G[i].clear();
while(m--){
scanf("%d%d", &u, &v);
G[u].push_back(v);
}
tarjan();
printf("%s\n", cnt == 1 ? "Yes" : "No");
}
return 0;
}