zoukankan      html  css  js  c++  java
  • 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 
    

    思路
      显然要想回到本身房间需要经历一个环的过程。
      对于每个起点来说,这个点要么在环上,要么可以通过一条链到达一个环然后再转回来。
      可以用染色法对于每个强连通分量染色。
      如果一个点在一个环里,它能得到的糖果数量就是环的大小。
      如果不在环里,就dfs循着邻边直到找到环为止,它所得到的糖果数就是这条链(起点到环上一点的父亲节点)长+环的大小。
    CODE
      1 #include <bits/stdc++.h>
      2 #define dbg(x) cout << #x << "=" << x << endl
      3 
      4 using namespace std;
      5 typedef long long LL;
      6 const int maxn = 1e5 + 7;
      7 
      8 int head[maxn], dfn[maxn], low[maxn], st[maxn];
      9 int cnt = 0, tot = 0, tim = 0, top = 1, n, cl = 0;
     10 int vis[maxn];
     11 int color[maxn];
     12 int ans[maxn];
     13 int nxt[maxn];
     14 int circle_size[maxn];
     15 
     16 /*
     17 head[],结构体edge:存边
     18 
     19 dfn[],low[]:tarjan中数组
     20 
     21 st[]:模拟栈
     22 
     23 out[]:出边
     24 
     25 sd[]:强连通分量存储
     26 
     27 dq[]:统计答案
     28 */
     29 
     30 template<class T>inline void read(T &res)
     31 {
     32     char c;T flag=1;
     33     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
     34     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
     35 }
     36 
     37 struct Edge{
     38     int nxt, to;
     39 }edge[maxn * 2];
     40 
     41 inline void BuildGraph(int from, int to)
     42 {
     43     cnt++;
     44     edge[cnt].to = to;
     45     edge[cnt].nxt = head[from];
     46     head[from] = cnt;
     47 }
     48 
     49 void tarjan(int x)
     50 {
     51     tim++;
     52     dfn[x] = low[x] = tim;
     53     st[top] = x;
     54     top++;
     55     vis[x] = 1;
     56     for(int i = head[x] ; i != 0; i = edge[i].nxt)
     57     {
     58         int u = edge[i].to;
     59         if(vis[u] == 0)
     60         {
     61             tarjan(u);
     62             low[x]=min(low[x],low[u]);
     63         }
     64         else if(vis[u] == 1)
     65                 low[x]=min(low[x],dfn[u]);
     66     }
     67     if(dfn[x] == low[x])
     68     {
     69         cl++;
     70         do
     71         {
     72             top--;
     73             color[st[top]] = cl;
     74             vis[st[top]] = -1;
     75         }while( st[top] != x );
     76     }
     77     return ;
     78 }
     79 
     80 void dfs(int u, int x, int step) {
     81     if(ans[x] != 0) {
     82         ans[u] = ans[x] + step;
     83         return ;
     84     }
     85     else dfs(u, nxt[x], step+1);
     86 }
     87 
     88 int main()
     89 {
     90     scanf("%d",&n);
     91     for ( int i = 1; i <= n; ++i ) {
     92         scanf("%d",&nxt[i]);
     93         BuildGraph(i, nxt[i]);
     94         if(i == nxt[i]) {
     95             ans[i] = 1;
     96         }
     97     }
     98     for ( int i = 1; i <= n; ++i ) {
     99         if( !vis[i] ) {
    100             tarjan(i);
    101         }
    102     }
    103     for ( int i = 1; i <= n; ++i) {
    104         circle_size[color[i]]++;
    105     }
    106     for ( int i = 1; i <= n; ++i) {
    107         if(circle_size[color[i]]  != 1) {
    108             ans[i] = circle_size[color[i]];     
    109         }
    110     }
    111     for ( int i = 1; i <= n; ++i) {
    112         if(ans[i] == 0) {
    113             dfs(i, nxt[i], 1);
    114         }
    115     }
    116     for ( int i = 1; i <= n; ++i) {
    117         printf("%d
    ",ans[i]);
    118     }
    119     return 0;
    120 }
    View Code
    
    
    
    
    
  • 相关阅读:
    spark SQL之 DataFrame和DataSet
    scala之 保留小数
    spark之 避免数据倾斜之 给名字分区(百家姓)
    hive之 'client_protocol' is unset!
    hive之报错:ls:cannot access '/usr/local/spark/lib/spark-assembly-*.jar':No such file or directory
    hive之 Error: Duplicate key name 'PCS_STATS_IDX' (state=42000,code=1061) ----Hive schematool -initSchema
    Maven中需要注意的点
    spark之 Idea操作
    scala之 一句话打印三角形
    scala 之 BaseDao
  • 原文地址:https://www.cnblogs.com/orangeko/p/12323721.html
Copyright © 2011-2022 走看看