• [USACO08DEC]在农场万圣节Trick or Treat on the Farm


    题目传送门

    solution

    首先看到这题,题目要求回到经过的点,那么很明显是形成了一个环,那么很容易想到是Tarjan,仔细一想,一个点只有两种情况,要么在环中,要么通过一条链与环相接。那么思路便很明显了,先缩点,记录各个环的大小,在环内的点的Ans值便是环的大小,在环外的点的Ans=点到环的最短距离+环的大小。

    但注意要特判环大小为1的情况。

    贴代码

    #include<bits/stdc++.h>
    using namespace std;
    const int Maxn=100005;
    int next[Maxn];
    int ans[Maxn];
    int head[Maxn],cnt;
    struct road
    {
        int to,next;
    }e[Maxn*2];
    void add(int a,int b)
    {
        cnt++;
        e[cnt].to=b;
        e[cnt].next=head[a];
        head[a]=cnt;
    }
    int sum,color[Maxn],low[Maxn],ins[Maxn],tim[Maxn],sta[Maxn],top=1,col;
    int Lemon[Maxn];
    void Tarjan(int x)
    {
        sum++;
        tim[x]=low[x]=sum;
        sta[top]=x;
        top++;
        ins[x]=1;
        for(int i=head[x];i!=0;i=e[i].next)
        {
            if(ins[e[i].to]==0)
            {
                Tarjan(e[i].to);
                low[x]=min(low[x],low[e[i].to]);
            }
            else if(ins[e[i].to]==1)
                 	low[x]=min(low[x],tim[e[i].to]);
        }
        if(tim[x]==low[x])
        {
            col++;
            do
            {
                top--;
                color[sta[top]]=col;
                ins[sta[top]]=-1;
            }while(sta[top]!=x);
        }
        return ;
    }
    void search(int root,int x,int step)
    {
        if(ans[x]!=0) {
                        ans[root]=ans[x]+step;
                        return ;
                      }
        else search(root,next[x],step+1);
    }
    int main()
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&next[i]);
            add(i,next[i]);
            if(next[i]==i) ans[i]=1;//注意特判环为1的情况。
        }
        for(int i=1;i<=n;i++)
            if(ins[i]==0) Tarjan(i);
        for(int i=1;i<=n;i++)
        	Lemon[color[i]]++;//记录环的大小
        for(int i=1;i<=n;i++)
        	if(Lemon[color[i]]!=1) ans[i]=Lemon[color[i]];//处理在环内的点
        for(int i=1;i<=n;i++)
        	if(ans[i]==0) search(i,next[i],1);//处理在环外的点。
        for(int i=1;i<=n;i++)
        	printf("%d
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    nginx 安装配置
    mysql分表
    冲刺day7
    冲刺day6
    冲刺day5
    冲刺day4
    冲刺day3
    冲刺day2
    冲刺day1
    撰写《需求规格说明书》的工作流程、组员分工和组员工作量比例
  • 原文地址:https://www.cnblogs.com/Le-mon/p/9200939.html
Copyright © 2020-2023  润新知