Tarjan算法

两篇讲的比较好的文章:

https://www.byvoid.com/blog/scc-tarjan/

https://www.byvoid.com/blog/biconnect/

对于有向图和无向图,处理的大体方法一样的,不过概念不同

/*****************************************************************************/

tarjan在处理无向图的时候,遇到两点之间的有多条边的时候处理方法,和如何缩点,缩边代码:

void tarjan(int s,int pre)
{
    low[s]=dfn[s]=cnt++;
    vis[s]=true;
    int f=0;
    stk.push(s);
    //stk[stkCnt++]=s;
    for (int i=head[s];i!=-1;i=e[i].next)
    {
        int u=e[i].to;
        if (u==pre){f++; continue;}
        if (!dfn[u]){
            tarjan(u,s);
            low[s]=min(low[s],low[u]);
        }
        else if(vis[u])
            low[s]=min(low[s],dfn[u]);
    }
    if (f>=2) return;//这里用f处理了点与点之间如果遇到多条边的情况
    if (low[s]==dfn[s]){
            while (true)
            {
                //int t=stk[--stkCnt];//stk.pop();
                int t=stk.top();stk.pop();
                flag[t]=xx;
                vis[t]=false;
                if (t==s)
                {
                    break;
                }
            }
            xx++;
    }
}
vector<int> *nMp;//[200010];
void build(int n)
{
   for (int i=0;i<n;i++)
   {//遍历所有的边,判断边的两边是不是在一个集合中的,不是就是割边
       int s,t;
       s=flag[e[i*2].from];
       t=flag[e[i*2].to];
       if (s!=t)
       {
           nMp[s].push_back(t);
           nMp[t].push_back(s);
       }
   }
}


2013多校的第二场B题(hdu 4612) ac代码:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <stack>
#include <algorithm>
using namespace std;
int n,m;
vector<int> mp[200010];
struct edge
{
    int from;
    int to;
    int next;
};
edge e[2000020];
int head[200020];
stack<int> stk;
//int stk[200010];
int stkCnt=0;
int flag[200010];
int xx;
int low[200010];
int dfn[200010];
bool vis[200010];
int cnt=0;
void tarjan(int s,int pre)
{
    low[s]=dfn[s]=cnt++;
    vis[s]=true;
    int f=0;
    stk.push(s);
    //stk[stkCnt++]=s;
    for (int i=head[s];i!=-1;i=e[i].next)
    {
        int u=e[i].to;
        if (u==pre){f++; continue;}
        if (!dfn[u]){
            tarjan(u,s);
            low[s]=min(low[s],low[u]);
        }
        else if(vis[u])
            low[s]=min(low[s],dfn[u]);
    }
    if (f>=2) return;
    if (low[s]==dfn[s]){
            while (true)
            {
                //int t=stk[--stkCnt];//stk.pop();
                int t=stk.top();stk.pop();
                flag[t]=xx;
                vis[t]=false;
                if (t==s)
                {
                    break;
                }
            }
            xx++;
    }
}
vector<int> *nMp;//[200010];
void build(int n)
{
  /*  for (int i=1;i<=n;i++)
   {
       for (int j=head[i];j!=-1;j=e[j].next)
       {
           if (flag[e[j].to]!=flag[i])
           {
               nMp[flag[i]].push_back(flag[e[j].to]);
               nMp[flag[e[j].to]].push_back(flag[i]);
           }
       }
   }*/
   for (int i=0;i<n;i++)
   {
       int s,t;
       s=flag[e[i*2].from];
       t=flag[e[i*2].to];
       if (s!=t)
       {
           nMp[s].push_back(t);
           nMp[t].push_back(s);
       }
   }
}

int ans,root;
void dfs(int now,int pre,int cnt)
{
    if (ans<=cnt)
    {
        ans=cnt;
        root=now;
    }
    for (int i=0;i<nMp[now].size();i++)
    {
        if (nMp[now][i]==pre) continue;
        dfs(nMp[now][i],now,cnt+1);
    }
}

int main()
{
//	int size = 256 << 20; // 256MB
//	char *p = (char*)malloc(size) + size;
//	__asm__("movl %0, %%esp\n" :: "r"(p) );

while (scanf("%d%d",&n,&m)!=EOF)
{
    xx=0;
    memset(flag,-1,sizeof(flag));
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    memset(vis,false,sizeof(vis));
   // memset(stk,0,sizeof(stk));
    memset(head,-1,sizeof(head));
    stkCnt=0;
    for (int i=0;i<n+5;i++) mp[i].clear();
    if (m+n==0) break;
    for (int i=0;i<2*m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        e[i].to=b;
        e[i].from=a;
        e[i].next=head[a];
        head[a]=i;
        i++;
        e[i].to=a;
        e[i].from=b;
        e[i].next=head[b];
        head[b]=i;
    }
    tarjan(1,1);
    nMp=new vector<int>[xx+10];
    build(m);
    ans=0;
    root=0;
    dfs(0,0,0);
    dfs(root,root,0);
    printf("%d\n",xx-1-ans);
   // delete mp;
    delete nMp;
}
    return 0;
}

你可能感兴趣的:(Tarjan算法)