tarjan模板

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack> 
#include<vector> 
using namespace std;
const int maxn=50010;
int first[maxn],to[maxn],next[maxn],cnt,from[maxn];
void add(int u,int v)
{
    from[++cnt]=u;
    to[cnt]=v;
    next[cnt]=first[u];
    first[u]=cnt;
}
int dfn[maxn],low[maxn],vis[maxn],ind,scc,now,st[maxn],top;
int isc[maxn];
vector<int> bl[maxn];
int blc;
int tag[maxn];
void Tarjan_dfs(int x,int fa)
{
    int son=0;
    low[x]=dfn[x]=++ind;
    for(int i=first[x];i;i=next[i])
    {
        int now=to[i];
        if(!dfn[now])
        {
            st[++top]=i;son++;
            Tarjan_dfs(now,x);
            low[x]=min(low[x],low[now]);
            if(low[now]>=dfn[x])
            {
                isc[x]=1;
                bl[++blc].clear();
                while(1)
                {
                    int num=st[top--];
                    if(tag[from[num]]!=blc)
                    {
                        bl[blc].push_back(from[num]);
                        tag[from[num]]=blc;
                    }
                    if(tag[to[num]]!=blc)
                    {
                        bl[blc].push_back(to[num]);
                        tag[to[num]]=blc;
                    }
                    if(to[num]==now && from[num]==x)break;
                }
            }
        }
        else if(dfn[now]<dfn[x] && now!=fa)
        {
            st[++top]=i;
            low[x]=min(low[x],dfn[now]);
        }
    }
    if(fa==0 && son==1)isc[x]=0;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    for(int i=1;i<=n;i++)if(!dfn[i])Tarjan_dfs(i,-1);
    cout<<blc<<endl;
    return 0;
}
点双联通

来自韩棒棒,输出点双的数量

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int n,m,order;
int low[20004],dfn[20004],father[20004],son[20004];
//father:父结点 son:子结点个数 
vector<int> edge[20004];
vector< pair<int,int> > cutedge;
void tarjan(int u)
{
    dfn[u]=low[u]=++order;
    for (int i=0;i<edge[u].size();i++)
    {
        int v=edge[u][i];
        if(!dfn[v])
        {
            son[u]++;
            father[v]=u;
             tarjan(v);
            if(low[v]>dfn[u]) cutedge.push_back(make_pair(min(v,u),max(v,u)));
            //边v-u为割边 
            low[u]=min(low[u],low[v]);
        }
        else if(v!=father[u]) low[u]=min(low[u],dfn[v]);
    }
    //根节点若有两棵或两棵以上的子树则该为割点
    //非根节点若所有子树节点均没有指向u的祖先节点的回边则为割点
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        edge[u].push_back(v),edge[v].push_back(u);
    }
    tarjan(1);
    sort(cutedge.begin(),cutedge.end());
    for(int i=0;i<cutedge.size();i++) printf("%d %d\n",cutedge[i].first,cutedge[i].second);
}
边双

输出桥,边双就是图删去桥后的联通块

posted @ 2017-10-31 15:17  秦こころ酱  阅读(106)  评论(0编辑  收藏  举报