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


    题目描述

    每年,在威斯康星州,奶牛们都会穿上衣服,收集农夫约翰在N(1<=N<=100,000)个牛棚隔间中留下的糖果,以此来庆祝美国秋天的万圣节。

    由于牛棚不太大,FJ通过指定奶牛必须遵循的穿越路线来确保奶牛的乐趣。为了实现这个让奶牛在牛棚里来回穿梭的方案,FJ在第i号隔间上张贴了一个“下一个隔间”Next_i(1<=Next_i<=N),告诉奶牛要去的下一个隔间;这样,为了收集它们的糖果,奶牛就会在牛棚里来回穿梭了。

    FJ命令奶牛i应该从i号隔间开始收集糖果。如果一只奶牛回到某一个她已经去过的隔间,她就会停止收集糖果。

    在被迫停止收集糖果之前,计算一下每头奶牛要前往的隔间数(包含起点)。

    输入格式

    第1行 整数n。

    第2行到n+1行 每行包含一个整数 next_i 。

    输出格式

    n行,第i行包含一个整数,表示第i只奶牛要前往的隔间数。

    样例解释

    有4个隔间

    隔间1要求牛到隔间1

    隔间2要求牛到隔间3

    隔间3要求牛到隔间2

    隔间4要求牛到隔间3

    牛1,从1号隔间出发,总共访问1个隔间;

    牛2,从2号隔间出发,然后到三号隔间,然后到2号隔间,终止,总共访问2个隔间;

    牛3,从3号隔间出发,然后到2号隔间,然后到3号隔间,终止,总共访问2个隔间;

    牛4,从4号隔间出发,然后到3号隔间,然后到2号隔间,然后到3号隔间,终止,总共访问3个隔间。

    输入输出样例

    输入样例#1: 复制
    4 
    1 
    3 
    2 
    3 
    
    输出样例#1: 复制
    1 
    2 
    2 
    3 
    

    本来以为是水题,被洛谷坑了2333。
    如果暴力模拟可以拿40分,之后想到记忆化搜索。
    记忆化搜索对于树是非常方便的,但无法处理环,那就先tarjan缩点。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<stack>
     5 using namespace std;
     6 const int N=100005;
     7 int n,tim,dcnt,next[N],nxt[N],dfn[N],low[N],belong[N],sz[N],ans[N];
     8 bool instk[N],vis[N];
     9 stack<int>stk;
    10 void tarjan(int u)
    11 {
    12     dfn[u]=low[u]=++tim;
    13     instk[u]=1;
    14     stk.push(u);
    15     if(next[u])
    16     {
    17         if(dfn[next[u]]==0)
    18         {
    19             tarjan(next[u]);
    20             low[u]=min(low[u],low[next[u]]);
    21         }
    22         else if(instk[next[u]])
    23             low[u]=min(low[u],dfn[next[u]]);
    24     }
    25     if(low[u]==dfn[u])
    26     {
    27         ++dcnt;
    28         while(1)
    29         {
    30             int t=stk.top();
    31             stk.pop();
    32             instk[t]=0;
    33             belong[t]=dcnt;
    34             sz[dcnt]++;
    35             if(t==u)
    36                 break;
    37         }
    38     }
    39 }
    40 void dfs(int u)
    41 {
    42     if(nxt[u])
    43     {
    44         if(!vis[nxt[u]])
    45         {
    46             dfs(nxt[u]);
    47             vis[nxt[u]]=1;
    48         }
    49         ans[u]=ans[nxt[u]]+sz[u];
    50     }
    51     else
    52     {
    53         ans[u]=sz[u];
    54         vis[u]=1;
    55     }
    56 }
    57 int main()
    58 {
    59     scanf("%d",&n);
    60     for(int i=1;i<=n;i++)
    61     {
    62         scanf("%d",&next[i]);
    63         if(next[i]==i)
    64             next[i]=0;
    65     }
    66     for(int i=1;i<=n;i++)
    67         if(!dfn[i])
    68             tarjan(i);
    69     for(int i=1;i<=n;i++)
    70         if(next[i]&&belong[i]!=belong[next[i]])
    71             nxt[belong[i]]=belong[next[i]];
    72     for(int i=1;i<=dcnt;i++)
    73         if(!vis[i])
    74         {
    75             dfs(i);
    76             vis[i]=1;
    77         }
    78     for(int i=1;i<=n;i++)
    79         printf("%d
    ",ans[belong[i]]);
    80     return 0;
    81 }
  • 相关阅读:
    Google I/O 官方应用中的动效设计
    浪院长 | spark streaming的使用心得
    Kubernetes 1.12公布:Kubelet TLS Bootstrap与Azure虚拟机规模集(VMSS)迎来通用版本号
    安卓自己定义View进阶-Path基本操作
    2014编程之美初赛第二场
    2015年,即将结束
    查看JVM运行时参数
    使用ThreadPoolExecutor线程池实现并发操作并返回结果
    mysql数据库将查询的多条结果的某些字段合并为一个字段处理
    mysql数据库使用mybatis新增操作返回自增主键的值
  • 原文地址:https://www.cnblogs.com/fantasquex/p/9342708.html
Copyright © 2020-2023  润新知