• tarjan缩点——在农场万圣节Trick or Treat on the Farm


    一个房间能到另一个房间,有向图,奶牛从自己编号(1到n)的点出发,如果回到以前到过的点就停止,问每头奶牛可以经过几个点;

    情况分两种,

    一,奶牛在环上,能走的是环的大小,二,一条链连接一个环,大小是链+环;

    要预先处理自环的答案(1),还有环的大小是1的(并不在环上的点);

    一开始还以为可能出现只有一条链没有环的,但是因为每个点都有一条出边,所以不必担心;

    #include<cstdio>
    #include<cstring>
    #include<stack>
    #include<algorithm>
    using namespace std;
    const int maxn=1e5+10;
    int pre[maxn*2],last[maxn],other[maxn*2],l;
    stack<int> s;
    void add(int x,int y)
    {
        l++;
        pre[l]=last[x];
        last[x]=l;
        other[l]=y;
    }
    int belong[maxn];
    int qw;
    int n;
    int ru[maxn];
    int cnt,dfn[maxn],low[maxn];
    int next[maxn];
    
    void dfs(int x)
    {
        s.push(x);
        dfn[x]=low[x]=++cnt;
        ru[x]=1;
        for(int p=last[x];p;p=pre[p])
        {
            int v=other[p];
            if(!dfn[v])
            {
                dfs(v);
                low[x]=min(low[x],low[v]);
            }
            else if(ru[v])
            {
                low[x]=min(low[x],dfn[v]);
            }
        }
        if(dfn[x]==low[x])
        {
            belong[x]=++qw;
            while(!s.empty())
            {
                int y=s.top();
                s.pop();
                ru[y]=0;
                belong[y]=qw;
                if(y==x) break;
            }
        }
    }
    int ring[maxn];
    int ans[maxn];
    
    void search(int x,int y,int stp)
    {
        if(ans[y])
        {
            ans[x]=ans[y]+stp;
            return ;
        }
        else search(x,next[y],stp+1);
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&next[i]);
            add(i,next[i]);
            if(next[i]==i) ans[i]=1;
        }
        
        for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i);//一定要注意图不一定都联通 
        for(int i=1;i<=n;i++)
        {
            ring[belong[i]]++;//记录环的大小 
        }
        for(int i=1;i<=n;i++)
        {
            if(ring[belong[i]]!=1) ans[i]=ring[belong[i]]; 
        }
        for(int i=1;i<=n;i++)
        {
            if(!ans[i]) search(i,next[i],1);
        }
        for(int i=1;i<=n;i++)
        {
            printf("%d
    ",ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    js冒泡排序的两种实现方式
    LeetCode SQL(一)
    k8s学习之Mac安装最新版本k8s
    docker 安装MySQL8.0设置主从复制
    代码中if的骚操作
    和别人说东西的时候要注意的点
    2021 五一深圳计划
    Swoole支持openssl扩展Mac版
    租房
    Mac常用的快捷键
  • 原文地址:https://www.cnblogs.com/WHFF521/p/11526185.html
Copyright © 2020-2023  润新知