二分图强连通分量 tarjan 模板

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<vector>
#define maxx 200000
using namespace std;
int a,b,c,d,n,m;
int cnt,fail,biao;

//cnt是每个强连通分量的编号
//fail是栈sta的指针
//biao用于给节点编号


int sta[maxx],belong[maxx],dnf[maxx],low[maxx];
//sta是栈
//belong[i]代表节点i所在的强连通分量编号
//dnf是每个节点的编号
//low其实我也不知道是啥,只要懂他的作用就ok

bool insta[maxx];//节点是否在栈中
vector<int> lin[maxx];//图

int tarjan(int i)
{
        int j;
        dnf[i]=low[i]=++biao;
        sta[++fail]=i;
        insta[i]=true;//编号并入栈
        for (unsigned k=0;k<lin[i].size();k++)
        {
                j=lin[i][k];
                if (dnf[j]==0)    //如果子节点没有编号
                {
                        tarjan(j);
                        low[i]=min(low[i],low[j]);//父亲节点low值是其子节点中low的最小值
                }
                else if (insta[j] && dnf[j]<low[i])
                        low[i]=dnf[j];   //好吧这句我不知道为啥,问了老师来补充
        }
        if (low[i]==dnf[i])//如果形成了一个环,即形成了一个强连通分量,出栈,更新belong数组
        {
                cnt++;
                do    //不会这一句的童鞋不要乱改这里,否则可能会错
                {
                        j=sta[fail--];
                        belong[j]=cnt;
                        insta[j]=0;
                }
                while(i!=j);
        }
}





int solve()
{
        for (int i=1;i<=n;i++)//初始化
        {
                vis[i]=0;
                insta[i]=false;
                sta[i]=0;
                belong[i]=0;
                dnf[i]=0;
                low[i]=0;
        }
        for (int i=1;i<=n;i++)
                if (dnf[i]==0)    //图可能不连通
                        tarjan(i);
}
int main()
    {

        n=6;
        lin[1].push_back(3);
        lin[1].push_back(2);
        lin[2].push_back(4);
        lin[3].push_back(5);
        lin[3].push_back(4);
        lin[4].push_back(1);
        lin[4].push_back(6);
        lin[5].push_back(6);

        solve();
        for(int i=1;i<=n;i++)
            cout<<belong[i]<<" ";
        cout<<endl;
        return 0;
    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值