zoukankan      html  css  js  c++  java
  • p2921 Trick or Treat on the Farm

    传送门

    题目

    每年万圣节,威斯康星的奶牛们都要打扮一番,出门在农场的N个牛棚里转 悠,来采集糖果.她们每走到一个未曾经过的牛棚,就会采集这个棚里的1颗糖果。农场不大,所以约翰要想尽法子让奶牛们得到快乐.他给每一个牛棚设置了一个“后继牛 棚”.牛棚i的后继牛棚是next_i 他告诉奶牛们,她们到了一个牛棚之后,只要再往后继牛棚走去, 就可以搜集到很多糖果.事实上这是一种有点欺骗意味的手段,来节约他的糖果.第i只奶牛从牛棚i开始她的旅程.请你计算,每一只奶牛可以采集到多少糖果.

    分析

    首先我们先进行Tarjan缩点,将每点权值赋为环中点数,意为走入这个环可获得的糖果数。因为只有一条出边,所以之后我们便进行dfs,从每一个点出发所获糖果数即为它自身权值+由它到达的点出发所能获得的糖果数。

    代码
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<ctime>
    #include<queue>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    int vis[110000],size[110000],nxt[110000],ist[110000],dfn[110000],low[110000];
    int sum,cnt,belong[110000],nxt2[110000],all[110000];
    stack<int>a;
    inline void read(int &x){
          int f=1;x=0;
          char s=getchar();
          while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
          while(s>='0'&&s<='9'){x=x*10+(s-'0');s=getchar();}
          x*=f;
    }
    inline void tarjan(int x){
          dfn[x]=low[x]=++cnt;
          a.push(x);
          ist[x]=1;
          if(!dfn[nxt[x]]){
              tarjan(nxt[x]);
              low[x]=min(low[x],low[nxt[x]]);
          }else if(ist[nxt[x]]){
              low[x]=min(low[x],dfn[nxt[x]]);
          }
          if(dfn[x]==low[x]){
              sum++;
              while(1){
                  int u=a.top();
                  a.pop();
                  ist[u]=0;
                  belong[u]=sum;
                  all[sum]++;
                  if(u==x)break;
              }
          }
    }
    inline void go(int x){
          if(size[x])return;
          size[x]=all[x];
          vis[x]=1;
          if(!nxt2[x])return;
          go(nxt2[x]);
          size[x]+=size[nxt2[x]];
    }
    int main(){
          int n,m,i,j,k;
          read(n);
          for(i=1;i<=n;i++)read(nxt[i]);
          for(i=1;i<=n;i++)
             if(!dfn[i])tarjan(i);
          for(i=1;i<=n;i++)
             if(belong[i]!=belong[nxt[i]])nxt2[belong[i]]=belong[nxt[i]];
          for(i=1;i<=sum;i++)
             if(!vis[i])
               go(i);
          for(i=1;i<=n;i++)printf("%d ",size[belong[i]]);
          return 0;
    }

  • 相关阅读:
    软件定义网络实验七:OpenDaylight 实验——Python中的REST API调用+选做
    软件定义网络实验六:OpenDaylight 实验——OpenDaylight 及 Postman 实现流表下发
    软件定义网络实验五:OpenFlow协议分析和OpenDaylight安装
    软件定义网络实验四:Open vSwitch 实验——Mininet 中使用 OVS 命令
    第一次个人编程作业
    软件定义网络实验三:Mininet 实验——拓扑的命令脚本生成
    软件定义网络实验二:Mininet 实验——拓扑的命令脚本生成
    软件定义网络实验一:Mininet源码安装和可视化拓扑工具
    第一次博客作业
    第一次个人编程作业
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/9123153.html
Copyright © 2011-2022 走看看