码迷,mamicode.com
首页 > 其他好文 > 详细

poj 2186 tarjan求强连通分量

时间:2016-05-22 06:11:26      阅读:110      评论:0      收藏:0      [点我收藏+]

标签:

蕾姐讲过的例题..玩了两天后才想起来做 貌似省赛之后确实变得好懒了...再努力两天就可以去北京玩了!

顺便借这个题记录一下求强连通分量的算法 

1 只需要一次dfs 依靠stack来实现的tarjan算法 每次走到一个点 马上把它压入栈中 每次对与这个点相连的点处理完毕 判断是否low[u]==dfn[u] 若是 开始退栈 直到栈顶元素等于u才退出(当栈顶元素等于u也需要pop) 每次一起退栈的点属于同一个强连通分量 储存图可以用链式前向星也可以用邻接矩阵更可以用vector 蕾姐说不会超时 我信了

2 需要两次dfs的kosara 在输入图的时候需要搞出来一个反向图以便第二次dfs使用 开始进行一次dfs 每当一个点要离开的时候就将其压入栈中 当所有的点都被遍历后 从栈顶元素开始进行反向搜索 一次搜到的点属于同一个强连通分量 其实..也需要用到栈...

需要注意的是 当使用tarjan时 dfs时如果判断dfn[v]时已经有了值 在else中需要有if条件(!id[v]) 

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<math.h>
#include<iostream>
#include<stack>
#include<vector>
using namespace std;
int n,m;
int id[10050];
int dfn[10050];
int low[10050];
int ans[10050];
int cd[10050];
int point[10050];
int num;
int cnt;
int tot;
vector<int >q[10050];
stack<int >s;
void init(){
for(int i=1;i<=n;i++)
{
    id[i]=0;
    dfn[i]=0;
    low[i]=0;
    ans[i]=0;
    cd[i]=0;
    point[i]=-1;
    q[i].clear();
}
num=cnt=tot=0;
while(!s.empty())
    s.pop();
}
void dfs(int u){
    dfn[u]=low[u]=++cnt;
    s.push(u);
    int v;
    int siz=q[u].size();
    for(int i=0;i<siz;i++)
    {
        v=q[u][i];
        if(!dfn[v])
        {
            dfs(v);
            low[u]=min(low[u],low[v]);

        }
        else if(!id[v])
        {
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u])
    {
        int temp=0;
        num++;
        while(!s.empty())
        {
            int v=s.top();
            s.pop();
            temp++;
            id[v]=num;
            if(v==u)
                break;
        }
        ans[num]=temp;
    }
}
struct node
{
    int v,nex;
};
node a[10050];
void add(int u,int v)
{
    a[tot].v=v;
    a[tot].nex=point[u];
    point[u]=tot;
    tot++;
}
void jt(){
for(int i=1;i<=n;i++)
{
    int siz=q[i].size();
    for(int k=0;k<siz;k++)
    {
        int v=q[i][k];
        if(id[v]!=id[i])
        {
            cd[id[i]]++;
        }
    }
}
}
void did(){
int can=0;
int p=-1;
for(int i=1;i<=num;i++)
{
    if(cd[i]==0)
    {
        can++;
        p=i;
    }
}
if(can==1)
{
    printf("%d\n",ans[p]);
}
else
    printf("0\n");
}
int main(){
while(cin>>n>>m)
{
    init();
    for(int i=1;i<=m;i++)
    {
        int u,v;
        cin>>u>>v;
        q[u].push_back(v);
    }
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
            dfs(i);
    }
    jt();
    did();
}
}

  

poj 2186 tarjan求强连通分量

标签:

原文地址:http://www.cnblogs.com/rayrayrainrain/p/5516038.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!