连通图

Strongly Connected Componenet

namespace Graph
{
    const int __=2e5+5;
    int n,v[__];//点权
    vectorG[__];

    void init(int _n)
    {
        n=_n;
        for(int i=1;i<=n;++i)
            G[i].clear();
    }

    void add_edge(int x,int y)//有向边
    {
        G[x].push_back(y);
    }
}

namespace SCC
{
    const int __=2e5+5;
    vectorG[__];//缩点后注意重边有影响使用set
    int n,idx,dfn[__],low[__],bel[__],s[__];//栈
    ll v[__];//缩点后的点权

    int dfs(int x)
    {
        if(dfn[x])return dfn[x];
        s[++*s]=x;
        dfn[x]=low[x]=++idx;
        for(int y:Graph::G[x])
            if(!bel[y])
                low[x]=min(low[x],dfs(y));
        if(low[x]==dfn[x])
            for(bel[x]=++n,v[n]=0;;--*s)
            {
                v[n]+=Graph::v[s[*s]];
                if(s[*s]==x){--*s;break;}
                else bel[s[*s]]=n;
            }
        return low[x];
    }

    void tarjan()//注意一个点的特判
    {
        idx=n=*s=0;
        for(int i=1;i<=Graph::n;++i)
            if(!dfn[i])dfs(i);
        for(int i=1;i<=Graph::n;++i)
            for(int y:Graph::G[i])
                if(bel[i]!=bel[y])
                    G[bel[i]].push_back(bel[y]);
    }

    void clear()
    {
        for(int i=1;i<=Graph::n;++i)
        {
            dfn[i]=bel[i]=0;
            G[i].clear();
        }
    }

    void print()
    {
        for(int i=1;i<=Graph::n;++i)
            printf("bel[%d]=%d\n",i,bel[i]);
        for(int i=1;i<=n;++i)
        {
            printf("%d:",i);
            for(int x:G[i])
                pf(" %d",x);
            putchar('\n');
        }
    }
}

割点(tarjan):

vectorG[105];
int low[105],dfn[105],cut[105],cont=1,ans=0;

void dfs(int fa,int x)
{
    int son=0;
    dfn[x]=low[x]=cont++;
    int len=G[x].size();
    for(int i=0; i=dfn[x]&&fa!=-1&&!cut[x])
            {
                cut[x]=1;
                ans++;
            }
        }
        else low[x]=min(low[x],dfn[nex]);
    }
    if(fa==-1&&son>1)
    {
        cut[x]=1;
        ans++;
    }
}

题目链接:Network(求割点个数)

tarjan:

vectorG[105];
int low[105],dfn[105],cut[105],cont=1,ans=0;

void dfs(int fa,int x)
{
    int son=0;
    dfn[x]=low[x]=cont++;
    int len=G[x].size();
    for(int i=0; i=dfn[x]&&fa!=-1&&!cut[x])
            {
                cut[x]=1;
                ans++;
            }
        }
        else low[x]=min(low[x],dfn[nex]);
    }
    if(fa==-1&&son>1)
    {
        cut[x]=1;
        ans++;
    }
}

void init(void)
{
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(cut,0,sizeof(cut));
    cont=1;     ans=0;
}

int main()
{
    int n,x,y;
    char ch;
    while(~scanf("%d",&n)&&n)
    {
        init();
        while(~scanf("%d",&x)&&x)
            while((ch=getchar())!='\n')
            {
                scanf("%d",&y);
                G[x].push_back(y);
                G[y].push_back(x);
            }
        for(int i=1; i<=n; i++)
            if(!dfn[i])dfs(-1,i);
        printf("%d\n",ans);
        for(int i=1; i<=n; i++)
            G[i].clear();
    }
    return 0;
}

题目链接:割点(求割点个数以及割点)

tarjan:

int low[100005],dfn[100005],cut[100005],cont=1,ans=0;
vectorG[100005];

void dfs(int fa,int x)
{
    int son=0;
    dfn[x]=low[x]=cont++;
    int len=G[x].size();
    for(int i=0; i=dfn[x]&&fa!=-1&&!cut[x])
            {
                cut[x]=1;
                ans++;
            }
        }
        else low[x]=min(low[x],dfn[nex]);
    }
    if(fa==-1&&son>1)
    {
        cut[x]=1;
        ans++;
    }
}

int main()
{
    int m,n,x,y;
    scanf("%d%d",&n,&m);
    for(int i=0; i

割边(tarjan):

int low[100005],dfn[100005],cont,ans;
vectorG[100005];
vector >bri;
void dfs(int fa,int x)
{
    dfn[x]=low[x]=cont++;
    int len=G[x].size();
    for(int i=0; idfn[x])
            {
                if(nex>x)bri.push_back(make_pair(x,nex));
                else bri.push_back(make_pair(nex,x));
                ans++;
            }
        }
        else low[x]=min(low[x],dfn[nex]);
    }
}

题目链接:Critical Links

tarjan:

int low[100005],dfn[100005],cont,ans;
vectorG[100005];
vector >bri;

void dfs(int fa,int x)
{
    dfn[x]=low[x]=cont++;
    int len=G[x].size();
    for(int i=0; idfn[x])
            {
                if(nex>x)bri.push_back(make_pair(x,nex));
                else bri.push_back(make_pair(nex,x));
                ans++;
            }
        }
        else low[x]=min(low[x],dfn[nex]);
    }
}

void init(void)
{
    bri.clear();
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    cont=1;
    ans=0;
}

int main()
{
    int T,n,x,y,m;
    while(~scanf("%d",&T))
    {
        init();
        n=T;
        while(T--)
        {
            scanf("%d (%d)",&x,&m);
            for(int i=0; i

题目链接:割边与割点

tarjan:

int low[20005],dfn[20005],cut[20005],cont,ans;
vectorG[20005];
vector >bri;
void dfs(int fa,int x)
{
    int son=0;
    dfn[x]=low[x]=cont++;
    int len=G[x].size();
    for(int i=0; idfn[x])  //桥
                if(nex>x)bri.push_back(make_pair(x,nex));
                else bri.push_back(make_pair(nex,x));
            if(low[nex]>=dfn[x]&&fa!=-1&&!cut[x])   //割点
            {
                ans++;
                cut[x]=1;
            }
        }
        else low[x]=min(low[x],dfn[nex]);
    }
    if(fa==-1&&son>1)   //根节点割点判定
    {
        cut[x]=1;
        ans++;
    }
}
void init(void)
{
    bri.clear();
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    cont=1;
    ans=0;
}
int main()
{
    int n,m,x,y;
    init();
    scanf("%d%d",&n,&m);
    for(int i=0; i

强联通分量:

题目链接:迷宫城堡

Kosaraju:

vectorG[10005];   //正向边
vectorGr[10005];  //反向边
stackS;
int vis[10005];
int m,n;

void dfs_normal(int node)
{
    vis[node]=1;
    int len=G[node].size();
    for(int i=0; i

题目链接:The Cow Prom

tarjan:

vectorG[50005];
int vis[50005];
int dfn[50005];
int low[50005];
int cont=1;
int n,m,ans=0;
stackS;

void dfs(int x)
{
    dfn[x]=low[x]=cont++;
    S.push(x);vis[x]=1;
    int len=G[x].size();
    for(int i=0; i1)ans++;
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    int x,y;
    for(int i=0; i

双联通分量:

题目链接:边的双连通分量

tarjan:

int low[20005],dfn[20005],cont,ans;
int bel[20005],minn[20005];
vectorG[20005];
stackS;

void dfs(int fa,int x)
{
    dfn[x]=low[x]=cont++;
    S.push(x);
    int len=G[x].size();
    for(int i=0;i

题目链接:点的双连通分量

tarjan:

struct node
{
    int nex,id;
} t;

struct edge
{
    int now,nex,id;
} temp;

int low[20005],dfn[20005],bel[100005],minn[100005],cont,ans;
bool vis[100005];
stackS;
vectorG[20005];

void dfs(int fa,int x)
{
    int son=0;
    dfn[x]=low[x]=cont++;
    int len=G[x].size();
    for(int i=0; i=dfn[x]&&fa!=-1)||(son>1&&fa==-1))
            {
                ans++;
                while(1)
                {
                    temp=S.top();
                    S.pop();
                    bel[temp.id]=ans;
                    minn[ans]=min(minn[ans],temp.id);
                    vis[temp.id]=true;
                    if(temp.now==x&&temp.nex==nex)break;
                }
            }
        }
        else low[x]=min(low[x],dfn[nex]);
    }
}

void init(int n)
{
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    memset(bel,0,sizeof(bel));
    memset(vis,false,sizeof(vis));
    cont=1;
    ans=0;
    for(int i=1; i<=n; i++)
        minn[i]=inf;
}

int main()
{
    int n,m,x,y;
    scanf("%d%d",&n,&m);
    init(m);
    for(int i=1; i<=m; i++)
    {
        scanf("%d%d",&x,&y);
        t.id=i;
        t.nex=y;
        G[x].push_back(t);
        t.nex=x;
        G[y].push_back(t);
    }
    for(int i=1; i<=n; i++)
        if(!dfn[i])dfs(-1,i);
    ans++;
    while(!S.empty())
    {
        temp=S.top();
        S.pop();
        bel[temp.id]=ans;
        minn[ans]=min(minn[ans],temp.id);
    }
    printf("%d\n",ans);
    for(int i=1; i<=m; i++)
        printf("%d ",minn[bel[i]]);
    return 0;
}

你可能感兴趣的:(连通图)