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


    题目描述

    Every year in Wisconsin the cows celebrate the USA autumn holiday of Halloween by dressing up in costumes and collecting candy that Farmer John leaves in the N (1 <= N <= 100,000) stalls conveniently numbered 1..N.

    Because the barn is not so large, FJ makes sure the cows extend their fun by specifying a traversal route the cows must follow. To implement this scheme for traveling back and forth through the barn, FJ has posted a 'next stall number' next_i (1 <= next_i <= N) on stall i that tells the cows which stall to visit next; the cows thus might travel the length of the barn many times in order to collect their candy.

    FJ mandates that cow i should start collecting candy at stall i. A cow stops her candy collection if she arrives back at any stall she has already visited.

    Calculate the number of unique stalls each cow visits before being forced to stop her candy collection.

    POINTS: 100

    每年万圣节,威斯康星的奶牛们都要打扮一番,出门在农场的N个牛棚里转 悠,来采集糖果.她们每走到一个未曾经过的牛棚,就会采集这个棚里的1颗糖果.

    农场不大,所以约翰要想尽法子让奶牛们得到快乐.他给每一个牛棚设置了一个“后继牛 棚”.牛棚i的后继牛棚是next_i 他告诉奶牛们,她们到了一个牛棚之后,只要再往后继牛棚走去, 就可以搜集到很多糖果.事实上这是一种有点欺骗意味的手段,来节约他的糖果.

    第i只奶牛从牛棚i开始她的旅程.请你计算,每一只奶牛可以采集到多少糖果.

    输入输出格式

    输入格式:

     

    * Line 1: A single integer: N

    * Lines 2..N+1: Line i+1 contains a single integer: next_i

     

    输出格式:

     

    * Lines 1..N: Line i contains a single integer that is the total number of unique stalls visited by cow i before she returns to a stall she has previously visited.

     

    输入输出样例

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

    说明

    Four stalls.

    * Stall 1 directs the cow back to stall 1.

    * Stall 2 directs the cow to stall 3

    * Stall 3 directs the cow to stall 2

    * Stall 4 directs the cow to stall 3

    Cow 1: Start at 1, next is 1. Total stalls visited: 1.

    Cow 2: Start at 2, next is 3, next is 2. Total stalls visited: 2. Cow 3: Start at 3, next is 2, next is 3. Total stalls visited: 2. Cow 4: Start at 4, next is 3, next is 2, next is 3. Total stalls visited: 3.

     思路:tarjin缩点+dfs。

    一开始是直接搜索:

    #include<map>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    map<int,int>ma[MAXN];
    int n,tot,tot1,tim,top,num,sumcol;
    int to[MAXN],net[MAXN],head[MAXN];
    int to1[MAXN],net1[MAXN],head1[MAXN];
    int stack[MAXN],visstack[MAXN],ans[MAXN];
    int low[MAXN],dfn[MAXN],vis[MAXN],col[MAXN],sum[MAXN];
    void add(int u,int v){
        to[++tot]=v;net[tot]=head[u];head[u]=tot;
    }
    void add1(int u,int v){
        to1[++tot1]=v;net1[tot1]=head1[u];head1[u]=tot1;
    }
    void tarjin(int now){
        low[now]=dfn[now]=++tim;
        vis[now]=1;visstack[now]=1;
        stack[++top]=now;
        for(int i=head[now];i;i=net[i])
            if(visstack[to[i]])
                low[now]=min(low[now],dfn[to[i]]);
            else if(!vis[to[i]]){
                tarjin(to[i]);
                low[now]=min(low[now],low[to[i]]);
            }
        if(low[now]==dfn[now]){
            col[now]=++sumcol;
            while(stack[top]!=now){
                col[stack[top]]=sumcol;
                visstack[stack[top]]=0;
                sum[sumcol]++;top--;
            }
            visstack[now]=0;top--;sum[sumcol]++;
        }
    }
    void dfs(int now){
        num+=sum[now];
        for(int i=head1[now];i;i=net1[i])
            dfs(to1[i]);
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            int x;scanf("%d",&x);
            add(i,x);
        }
        for(int i=1;i<=n;i++)
            if(!vis[i])    tarjin(i);
        for(int i=1;i<=n;i++)
            for(int j=head[i];j;j=net[j])
                if(col[i]!=col[to[j]])
                    if(ma[col[i]].find(col[to[j]])==ma[col[i]].end()){
                        ma[col[i]][col[to[j]]]=1;
                        add1(col[i],col[to[j]]);
                    }
        for(int i=1;i<=sumcol;i++){ num=0;dfs(i);ans[i]=num; }
        for(int i=1;i<=n;i++)    cout<<ans[col[i]]<<endl;
    }
    40分暴力

    后来改成记忆化搜索就AC了

    #include<map>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    map<int,int>ma[MAXN];
    int n,tot,tot1,tim,top,num,sumcol;
    int to[MAXN],net[MAXN],head[MAXN];
    int to1[MAXN],net1[MAXN],head1[MAXN];
    int stack[MAXN],visstack[MAXN],ans[MAXN];
    int low[MAXN],dfn[MAXN],vis[MAXN],col[MAXN],sum[MAXN];
    void add(int u,int v){
        to[++tot]=v;net[tot]=head[u];head[u]=tot;
    }
    void add1(int u,int v){
        to1[++tot1]=v;net1[tot1]=head1[u];head1[u]=tot1;
    }
    void tarjin(int now){
        low[now]=dfn[now]=++tim;
        vis[now]=1;visstack[now]=1;
        stack[++top]=now;
        for(int i=head[now];i;i=net[i])
            if(visstack[to[i]])
                low[now]=min(low[now],dfn[to[i]]);
            else if(!vis[to[i]]){
                tarjin(to[i]);
                low[now]=min(low[now],low[to[i]]);
            }
        if(low[now]==dfn[now]){
            col[now]=++sumcol;
            while(stack[top]!=now){
                col[stack[top]]=sumcol;
                visstack[stack[top]]=0;
                top--;sum[sumcol]++;
            }
            visstack[now]=0;top--;sum[sumcol]++;
        }
    }
    void dfs(int now){
        if(ans[now])    return ;
        ans[now]+=sum[now];
        for(int i=head1[now];i;i=net1[i]){
            dfs(to1[i]);
            ans[now]+=ans[to1[i]];
        }   
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            int x;scanf("%d",&x);
            add(i,x);
        }
        for(int i=1;i<=n;i++)
            if(!vis[i])    tarjin(i);
        for(int i=1;i<=n;i++)
            for(int j=head[i];j;j=net[j])
                if(col[i]!=col[to[j]])
                    if(ma[col[i]].find(col[to[j]])==ma[col[i]].end()){
                        ma[col[i]][col[to[j]]]=1;
                        add1(col[i],col[to[j]]);
                    }
        for(int i=1;i<=n;i++)    dfs(col[i]);
        for(int i=1;i<=n;i++)    cout<<ans[col[i]]<<endl;
    }
     
    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    java第十三周作业
    java第十三周随堂
    安卓作业
    5.29 第十三周作业
    5.28第十三周上机练习
    5.22第十二周作业
    5.21第十二章上机练习
    5.15 第十一周作业
    5.14 第十一周 上机练习
    5.7第十周上机练习
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/8747306.html
Copyright © 2020-2023  润新知