【模板】Tarjan

15 篇文章 0 订阅
2 篇文章 0 订阅

出发前一个小时在颓一波板子

void tarjan(int x)
{
    dfn[x]=++num_dfn;
    low[x]=num_dfn;
    ifin[x]=true;
    zhan[++top]=x;
    for (int i=head[x]; i!=0; i=edge[i].next)
    {
        int to=edge[i].to;
        if (!dfn[to])
        {
            tarjan(to);
            low[x]=min(low[x],low[to]);
        }
        else if (ifin[to]) low[x]=min(low[x],dfn[to]);
    }
    if (dfn[x]==low[x])
    {
        ifin[x]=false;
        color[x]=++num_col;
        while (zhan[top]!=x)
        {
            int now=zhan[top--];
            ifin[now]=false;
            color[now]=num_col;
        }
        top--;//不要忘记把x弹出来,此时找到了以x为根(或x)一个强联通分量
    }

一道板子题:
刻录光盘
此题需要缩点;

if (color[edge[i].from]!=color[edge[i],to]]  du[color[edge[i].to]]++;
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int MAXN=100001;
struct Edge{
    int from,next,to;
}edge[MAXN];

int n,top,x,num_col,num_dfn,color[MAXN],dfn[MAXN],low[MAXN],zhan[MAXN];
bool ifin[MAXN];
bool b[MAXN];

int num_edge,head[MAXN];
void add_edge(int from,int to)
{
    edge[++num_edge].next=head[from];
    edge[num_edge].to=to;
    edge[num_edge].from=from;
    head[from]=num_edge;
}

void tarjan(int x)
{
    dfn[x]=++num_dfn;
    low[x]=num_dfn;
    zhan[++top]=x;
    ifin[x]=true;
    for (int i=head[x]; i!=0; i=edge[i].next)
    {
        int to=edge[i].to;
        if (!dfn[to])
        {
            tarjan(to);
            low[x]=min(low[to],low[x]);
        }
        else if (ifin[to]) low[x]=min(low[x],dfn[to]);
    }
    if (dfn[x]==low[x])//找到一个强联通分量 
    {
        ifin[x]=false;
        color[x]=++num_col;
        while (zhan[top]!=x)
        {
            int now=zhan[top--]; 
            ifin[now]=false;
            color[now]=num_col;
        }
        top--;
    }
}

int main()
{
    scanf("%d",&n);
    for (int i=1; i<=n; i++)
    {
        scanf("%d",&x);
        while (x)
        {
            add_edge(i,x);
            scanf("%d",&x);
        }
    }
    for (int i=1; i<=n; i++)
        if (!dfn[i]) tarjan(i);
//  printf("%d",num_col);
    int ans=0;
    for (int i=1; i<=num_edge; i++)
        if (color[edge[i].from]!=color[edge[i].to])
            b[color[edge[i].to]]=true;
    for (int i=1; i<=num_col; i++)
        if (!b[i]) ans++;
    printf("%d",ans);
    return 0;
}
/*
5
2 3 4 0
4 5 0
0
0
1 0
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值