Tarjan求强连通分量 缩点

//定义DFN(u)为节点u搜索的次序编号(时间戳)。Low(u)为u或者u的子树能够追溯到的最早的栈中的节点的次序号。
/*
poj3177
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string.h>
using namespace std;

const int N=5005;
const int M=100005;

struct Edge{
   int v,next;
}edge[2*M];

int head[N],low[N],dfn[N],belong[N],degree[N],sta[N];
bool vis[N];
int index,cnt,top,scc;

void addedge(int u,int v)
{
    edge[index].v=v;
    edge[index].next=head[u];
    head[u]=index++;
}

void Tarjan(int u,int fa)
{
    int i,v;
    low[u]=dfn[u]=++cnt;
    sta[++top]=u;
    vis[u]=true;
    for(int i=head[u];i!=-1;i=edge[i].next){
        v=edge[i].v;
        if(i==(fa^1))continue;
        if(!dfn[v]){
            Tarjan(v,i);
            low[u]=min(low[u],low[v]);
        }
        else if(vis[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(dfn[u]==low[u]){
        scc++;
        while(1){
         v=sta[top--];
         vis[v]=false;
         belong[v]=scc;
         if(v==u)break;
        }
    }
}


int main()
{
    int m,n,u,v,i,j;
    cin>>n>>m;
    index=top=scc=0;
    memset(head,-1,sizeof(head));
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    memset(vis,false,sizeof(vis));
    memset(degree,0,sizeof(degree));
    for(int i=0;i<m;i++){
        cin>>u>>v;
        addedge(u,v);
        addedge(v,u);
    }
    for(i=1;i<=n;i++){}
    if(!dfn[i])Tarjan(1,-1);
    for(i=1;i<=n;i++){
        for(j=head[i];j!=-1;j=edge[j].next){
            v=edge[j].v;
            if(belong[i]!=belong[v])
                degree[belong[i]]++;
        }
    }
    int sum=0;
    for(int i=1;i<=n;i++)
        if(degree[i]==1)sum++;
    cout<<(sum+1)/2<<endl;
    return 0;
}
*/

//poj3352
/*
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<string.h>
using namespace std;

const int N=5005;
const int M=100005;

struct Edge{
   int v,next;
}edge[2*M];

int head[N],low[N],dfn[N],belong[N],degree[N],sta[N];
bool vis[N];
int index,cnt,top,scc;

void addedge(int u,int v)
{
    edge[index].v=v;
    edge[index].next=head[u];
    head[u]=index++;
}

void Tarjan(int u,int fa)
{
    int i,v;
    low[u]=dfn[u]=++cnt;
    sta[++top]=u;
    vis[u]=true;
    for(int i=head[u];i!=-1;i=edge[i].next){
        v=edge[i].v;
        if(i==(fa^1))continue;
        if(!dfn[v]){
            Tarjan(v,i);
            low[u]=min(low[u],low[v]);
        }
        else if(vis[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(dfn[u]==low[u]){
        scc++;
        while(1){
         v=sta[top--];
         vis[v]=false;
         belong[v]=scc;
         if(v==u)break;
        }
    }
}


int main()
{
    int m,n,u,v,i,j;
    cin>>n>>m;
    index=top=scc=0;
    memset(head,-1,sizeof(head));
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    memset(vis,false,sizeof(vis));
    memset(degree,0,sizeof(degree));
    for(int i=0;i<m;i++){
        cin>>u>>v;
        addedge(u,v);
        addedge(v,u);
    }
    for(i=1;i<=n;i++){}
    if(!dfn[i])Tarjan(1,-1);
    for(i=1;i<=n;i++){
        for(j=head[i];j!=-1;j=edge[j].next){
            v=edge[j].v;
            if(belong[i]!=belong[v])
                degree[belong[i]]++;
        }
    }
    int sum=0;
    for(int i=1;i<=n;i++){
    if(degree[i]==1)sum++;
}
    cout<<(sum+1)/2<<endl;
    return 0;
}
*/


//poj1236
/*
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string.h>
#include<string>
#include<vector>
#include<stack>
using namespace std;

const int N=105;

vector<int> G[N];
int head[N],dfn[N],low[N],in[N],out[N];
int belong[N];
bool vis[N];
stack<int>sta;
int index,cnt,top,scc;


void Tarjan(int u)
{
    int i,v;
    low[u]=dfn[u]=++cnt;
    sta.push(u);
    vis[u]=true;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(!dfn[v]){
            Tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(vis[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u]){
        scc++;
        while(true){
            int x=sta.top();sta.pop();
            vis[x]=false;
            belong[x]=scc;
            if(x==u)break;
        }
    }
}


int main()
{
    int n;
    scc=0;
    memset(head,-1,sizeof(head));
    memset(belong,0,sizeof(belong));
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    memset(vis,false,sizeof(false));
    for(int i=0;i<N;i++)
        G[i].clear();
    cin>>n;
    for(int i=1;i<=n;i++){
        int v;
        while(cin>>v){
            if(v==0)break;
            G[i].push_back(v);
        }
    }
    for(int i=1;i<=n;i++){
        if(!dfn[i])Tarjan(i);
    }
    if(scc==1){
        cout<<1<<endl<<0<<endl;
        return 0;
    }
    for(int i=1;i<=n;i++){
        for(int j=0;j<G[i].size();j++){
            int v=G[i][j];
              if(belong[i]!=belong[v]){
            out[belong[i]]++;
            in[belong[v]]++;
           }
        }
    }
    int ans1=0,ans2=0;
    for(int i=1;i<=scc;i++){
        if(in[i]==0)ans1++;
        if(out[i]==0)ans2++;
    }
    cout<<ans1<<endl<<max(ans2,ans1)<<endl;
    return 0;
}
*/


//poj2186
/*
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string.h>
#include<vector>
using namespace std;


const int N=10005;
const int M=50010;


vector<int>G[N];
int scc,index,cnt,top;
int belong[N],fa[N],out[N],dfn[N],low[N],sta[N];
bool vis[N];
int sum[N];
int Sum;
int n,m;
int ans=0;


int find(int x)
{
    if(x==fa[x])return x;
    return fa[x]=find(fa[x]);
}

void Union(int u,int v)
{
    if(find(u)==find(v))return;
    u=find(u),v=find(v);
    fa[u]=v;
    Sum--;
}


void Tarjan(int u)
{
    vis[u]=true;
    low[u]=dfn[u]=++cnt;
    sta[++top]=u;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(!dfn[v]){
            Tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(vis[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(dfn[u]==low[u]){
        scc++;
        while(true){
            int v=sta[top--];
            vis[v]=false;
            belong[v]=scc;
            sum[scc]++;
            if(v==u)break;
        }
    }
}

int main()
{
    cin>>n>>m;
    Sum=n;
    memset(out,0,sizeof(out));
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    memset(sum,0,sizeof(sum));
    memset(vis,false,sizeof(vis));
    for(int i=0;i<N;i++)
        fa[i]=i,G[i].clear();
    cnt=0,scc=0,top=0;
    for(int i=0;i<m;i++){
        int u,v;
        cin>>u>>v;
        G[u].push_back(v);
        Union(u,v);
    }
    if(Sum!=1){
        ans=0;
    }
    else{
        for(int i=1;i<=n;i++)
            if(!dfn[i])Tarjan(i);
        for(int i=1;i<=n;i++){
            for(int j=0;j<G[i].size();j++){
                int v=G[i][j];
                if(belong[i]!=belong[v]){
                    out[belong[i]]++;
                }
            }
        }
        int Count=0;
        for(int i=1;i<=scc;i++){
            if(out[i]==0){
                Count++;
                ans=sum[i];
            }
        }
        if(Count>1)ans=0;
    }
    cout<<ans<<endl;
    return 0;
}
*/





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值