有向图的强连通分量的tarjan算法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37275680/article/details/82118407

此篇文章的整理仅用于学习记录,供日后复习,大部分内容来源于北大郭炜老师整理的课件。

1.POJ2186:Popular Cows

题意:给定一个有向图,求有多少顶点是由任何顶点出发都可达的。

有用的定理:有向无环图中唯一出度为0的点,一定可以有任何点出发均可达(由于无环,所以从任何点出发往前走必然终止于一个出度为0的点)

解题思路:1.求出所有强连通分量;

2.每个强连通分量缩成一个点,则形成一个有向无环图DAG。

3.DAG上面如果有唯一的出度为0的点,则该点能被所有的点可达。那么该点所代表的连通分量上的所有的原图中的点,都能被原图中的所有点可达,则该连通分量的点数,就是答案。

4.DAG上面如果有不止一个出度为0的点,则这些点互相不可达,原问题无解,答案为0.

缩点的时候不一定要构造新图,只要把不同强连通分量的点染不同颜色,然后考察各种颜色的点有没有连到别的颜色的边即可(即其对应的缩点后的DAG图上的点是否有出边)。

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int maxn=1e4+10;
const int maxm=5e4+10;
int n,m,dfn[maxn],low[maxn],tot=0,stck[maxn],r=0,cnt=0,pos[maxn],sum[maxn];
int outd[maxn];  //出度 
vector<int> sons[maxn];
 
void tarjan(int u){
    dfn[u]=low[u]=++tot;
    stck[++r]=u;
    for(int i=0;i<sons[u].size();i++){
        int v=sons[u][i];
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }else if(!pos[v]){  //pos[v]表明该强连通分量还在栈中 
            low[u]=min(low[u],dfn[v]);
        }
    }
    
    if(dfn[u]==low[u]){
        int len=r;
        cnt++; //染色编号
        while(stck[r]!=u) pos[stck[r--]]=cnt;  //缩点 
        pos[u]=cnt;
        r--;
        sum[cnt]=len-r;  //该强连通分量中总的结点数 
        //cout<<"len-r="<<len-r<<",len="<<len<<",r="<<r<<endl;
        //printf("sum[%d]=%d\n",cnt,sum[cnt]);
    }
}
 
int main(){
    scanf("%d%d",&n,&m);
    int x,y;
    for(int i=0;i<m;i++){
        scanf("%d%d",&x,&y);
        sons[x].push_back(y);
    }
    for(int i=1;i<=n;i++){
        if(!dfn[i]) tarjan(i);
    }
    
    for(int i=1;i<=n;i++){
        for(int j=0;j<sons[i].size();j++){
        	int v=sons[i][j];
        	if(pos[i]!=pos[v]) outd[pos[i]]++;
		}
    }
    
    int ans=0;
    bool flag=false;
    //cout<<"cnt="<<cnt<<endl;
    for(int i=1;i<=cnt;i++){
    	//cout<<"sum["<<i<<"]="<<sum[i]<<endl;
    	if(outd[i]==0) {
    		if(!flag){
    			ans=sum[i];
    			flag=true;
			}else{
				ans=0;
				break;
			}
		}
	}
    printf("%d\n",ans);
    return 0;
}

2.POJ1236: Network of Schools


 

猜你喜欢

转载自blog.csdn.net/qq_37275680/article/details/82118407