zoukankan      html  css  js  c++  java
  • P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm

    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号隔间开始收集糖果。如果一只奶牛回到某一个她已经去过的隔间,她就会停止收集糖果。

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

    Solution

    看到环直接想到 (Tarjan)
    因为每个点出度都为 (1), 所以此图只能构成简单环
    对于询问的每个点, 分两种情况讨论:

    1. 此点在环内: 显然答案为环的大小
    2. 此点不在环内: 答案为顺着路径走到最近环经过的点数 + 最近环的大小

    在环内很好确认, 当此点所在的颜色块包含点数大于等于 (2) 个则为环
    有一种特殊情况为自环, 此题中出边只有一条, 判断一下出边连向自己即可

    再环外的话通过 (dfs) 遍历图 , 直到找到环内节点即可
    用记忆化减少遍历量

    Code

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define LL long long
    #define REP(i, x, y) for(int i = (x);i <= (y);i++)
    using namespace std;
    int RD(){
        int out = 0,flag = 1;char c = getchar();
        while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
        while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
        return flag * out;
        }
    const int maxn = 100019,INF = 1e9 + 19;
    int head[maxn],nume = 1;
    struct Node{
        int v,dis,nxt;
        }E[maxn << 3];
    void add(int u,int v,int dis){
        E[++nume].nxt = head[u];
        E[nume].v = v;
        E[nume].dis = dis;
        head[u] = nume;
        }
    int num;
    int DFN[maxn], LOW[maxn], Index;
    int S[maxn], top;
    bool ins[maxn];
    int numc, col[maxn], nc[maxn];
    void Tarjan(int u){
    	DFN[u] = LOW[u] = ++Index;
    	S[++top] = u;ins[u] = 1;
    	for(int i = head[u];i;i = E[i].nxt){
    		int v = E[i].v;
    		if(!DFN[v])Tarjan(v), LOW[u] = min(LOW[u], LOW[v]);
    		else if(ins[v])LOW[u] = min(LOW[u], DFN[v]);
    		}
    	if(DFN[u] == LOW[u]){
    		numc++;
    		while(S[top + 1] != u){
    			col[S[top]] = numc;
    			nc[numc]++;
    			ins[top--] = 0;
    			}
    		}
    	}
    int dp[maxn];
    int DP(int u){
    	if(dp[u] != 0)return dp[u];//记忆化
    	if(nc[col[u]] > 1){dp[u] = nc[col[u]];return dp[u];}//环内
    	for(int i = head[u];i;i = E[i].nxt){
    		int v = E[i].v;
    		if(v == u){dp[u] = 1;return dp[u];}//自环
    		dp[u] = DP(v) + 1;//链上
    		}
    	return dp[u];
    	}
    int main(){
    	num = RD();
    	REP(i, 1, num){
    		int v = RD();
    		add(i, v, 1);
    		}
    	REP(i, 1, num)if(!DFN[i])Tarjan(i);
    	REP(i, 1, num){
    		printf("%d
    ", DP(i));
    		}
    	return 0;
    	}
    
  • 相关阅读:
    80211-pcap包类型有3种link type
    node搭建多人博客
    mac快捷键
    阿里云搭建svn
    linux 常用命令
    node 日志
    启动tomcat
    kill redis
    利用新浪接口获取客户端ip
    网站loading的几种实现方法
  • 原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9800695.html
Copyright © 2011-2022 走看看