kosaraju算法
大概思路:正向存储图,用vector t[N]表示,反向存储图,用vector rt[N]表示,先深搜正向图,并按遍历到的顺序入栈;然后依次取栈顶元素并删除栈顶元素,以此为起点深搜反向图,每深搜一次,强连通分量个数加一。
模板
#include <iostream>
#include <vector>
#include <stack>
#include <string.h>
#include <memory.h>
#include <cstdio>
#include <stdio.h>
using namespace std;
const int N = 10005;
vector<int> t[N],rt[N];
bool visit[N];
stack<int> s;
int n,m;
void dfs(int v){
visit[v]=1;
for(int i=0;i<t[v].size();i++){
if(!visit[t[v][i]]){
dfs(t[v][i]);
}
}
s.push(v);
}
void r_dfs(int v){
visit[v]=1;
for(int i=0;i<rt[v].size();i++){
if(!visit[rt[v][i]]){
r_dfs(rt[v][i]);
}
}
}
int kosaraju(){
//这个if语句我也不知道干嘛的,为什么要有。。
if(!s.empty()){
s.pop();
}
memset(visit,0,sizeof(visit));
for(int i=1;i<=n;i++){
if(!visit[i]){
dfs(i);
}
}
memset(visit,0,sizeof(visit));
int t=0;
while(!s.empty()){
int node=s.top();
s.pop();
printf("|%d| ", node );
if(!visit[node]){
t++;
r_dfs(node);
}
}
return t;
}
int main(){
//freopen("in.txt","r",stdin);
int x,y;
cin>>n>>m;
for(int i=0;i<m;i++){
cin>>x>>y;
t[x].push_back(y);
rt[y].push_back(x);
}
for(int i=0;i<n;i++){
for(int j=0;j<t[i].size();j++){
cout<<i<<" "<<j<<" "<<t[i][j]<<" "<<endl;
}
}
cout<<"\n";
cout<<kosaraju()<<endl;
return 0;
}
我写的模板和百科的不太一样。但是大同小异;
n代表节点个数,m代表有向边个数。(之前一直纠结为什么会出现节点5和两个强连通分量。。。看图)
输入
5 5
1 2
2 1
2 3
3 4
4 1
poj2186-Popular Cows
此题用到 kosaraju算法,以及所谓“缩点“的思想;
“缩点”就是将属于同一连通分量的元素赋予同一值;sd[i]的值代表i元素所属的联通分量;如果sd[i]==sd[j],说明i,j属于同一联通分量;
参考前辈的代码写出来的
#include <iostream>
#include <vector>
#include <stack>
#include <string.h>
#include <memory.h>
#include <cstdio>
#include <stdio.h>
using namespace std;
const int N = 10005;
vector<int> t[N],rt[N];
bool visit[N];
stack<int> s;
int n,m,num;
int sd[N],gs[N];
//若顶点i,j属于同一强连通分量,赋同一值;
//gs[i]记录的是第i个强连通分量的内顶点个数
void dfs(int v){
visit[v]=1;
for(int i=0;i<t[v].size();++i){
if(!visit[t[v][i]]){
dfs(t[v][i]);
}
}
s.push(v);
}
void r_dfs(int v){
sd[v]=num;
gs[num]++;
visit[v]=1;
for(int i=0;i<rt[v].size();++i){
if(!visit[rt[v][i]]){
r_dfs(rt[v][i]);
}
}
}
void kosaraju(){
if(!s.empty()){
s.pop();
}
memset(visit,0,sizeof(visit));
for(int i=1;i<=n;i++){
if(!visit[i]){
dfs(i);
}
}
num=0;
memset(visit,0,sizeof(visit));
memset(gs,0,sizeof(gs));
while(!s.empty()){
int node=s.top();
s.pop();
if(!visit[node]){
num++;
r_dfs(node);
}
}
}
void s_j(int n){
memset(visit,0,sizeof(visit));
for(int i=1;i<=n;i++){
for(int j=0;j<t[i].size();j++){
int temp=t[i][j];
if(sd[i]!=sd[temp]){
visit[sd[i]]=1;
}
}
}
int g,ans;
g=0;
for(int i=1;i<=num;i++){
if(!visit[i]){
ans=i;
g++;
}
}
if(g==1){
cout<<gs[ans]<<endl;
}
else {
cout<<0<<endl;
}
}
int main(){
//freopen("in.txt","r",stdin);
int x,y;
cin>>n>>m;
for(int i=0;i<m;i++){
cin>>x>>y;
t[x].push_back(y);
rt[y].push_back(x);
}
kosaraju();
s_j(n);
return 0;
}
poj1236-Network of Schools
题目大意及思路均参考自
补充:输入时第i行的输入a,b,0;代表存在i指向a,i指向b的有向边;
代码
#include <iostream>
#include <vector>
#include <stack>
#include <string.h>
#include <memory.h>
#include <cstdio>
#include <stdio.h>
#include <math.h>
using namespace std;
const int N = 10005;
vector<int> t[N],rt[N];
int visit[N];
stack<int> s;
int n,m,cnt,temp,numin,numout;
int belong[N],indu[N],outdu[N];
void dfs(int x){
visit[x]=1;
for(int i=0;i<t[x].size();i++){
if(!visit[t[x][i]]){
dfs(t[x][i]);
}
}
s.push(x);
}
void r_dfs(int x){
visit[x]=1;
belong[x]=cnt;
for(int i=0;i<rt[x].size();i++){
if(!visit[rt[x][i]]){
r_dfs(rt[x][i]);
}
}
}
void kosaraju(){
memset(visit,0,sizeof(visit));
for(int i=1;i<=n;i++){
if(!visit[i]){
dfs(i);
}
}
memset(visit,0,sizeof(visit));
while(!s.empty()){
temp=s.top();
s.pop();
if(!visit[temp]){
cnt++;
r_dfs(temp);
}
}
}
void count_du(){
for(int i=1;i<=n;i++){
outdu[i]=0;
indu[i]=0;
}
for(int i=1;i<=n;i++){
for(int j=0;j<t[i].size();j++){
int zhi=t[i][j];
if(belong[i]!=belong[zhi]){
outdu[belong[i]]++;
indu[belong[zhi]]++;
}
}
}
for(int i=1;i<=cnt;i++){
if(!outdu[i]){
numout++;
}
if(!indu[i]){
numin++;
}
}
if(cnt==1){
cout<<"1\n0\n"<<endl;
}
else{
cout<<numin<<"\n"<<max(numin,numout)<<endl;
}
}
int main(){
//freopen("in.txt","r",stdin);
cin>>n;
m=0;
cnt=0;numin=0;numout=0;
for(int i=1;i<=n;i++){
int x;
cin>>x;
while(x!=0){
m++;
t[i].push_back(x);
rt[x].push_back(i);
cin>>x;
}
}
kosaraju();
count_du();
return 0;
}