zoukankan      html  css  js  c++  java
  • Luogu P2921 在农场万圣节 【tarjan in 有向图】 By cellur925

    题目传送门

    上来就想到既直接又简单的暴力方法,顺着每个房间的下一个走下去就好了,但是没想到最坏情况会达到1e5,100000的数据铁定超时。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 
     5 using namespace std;
     6 
     7 int n;
     8 int nex[100090],ans[10090];
     9 bool vis[100090];
    10 
    11 int dfs(int u)
    12 {
    13     int sum=1,x=u;bool flag=1;
    14     memset(vis,0,sizeof(vis));
    15     vis[u]=1;
    16     while(flag)
    17     {
    18         int y=nex[x];
    19         if(vis[y]) flag=0;
    20         vis[y]=1;x=y;sum++;
    21     }
    22     sum--;
    23     return sum;
    24 }
    25 
    26 int main()
    27 {
    28     scanf("%d",&n);
    29     for(int i=1;i<=n;i++)
    30         scanf("%d",&nex[i]);
    31     for(int i=1;i<=n;i++)
    32         ans[i]=dfs(i);
    33     for(int i=1;i<=n;i++)
    34         printf("%d
    ",ans[i]);
    35     return 0;
    36 }
    40 pts

    正解:tarjan算法。

    去到奶牛去过的隔间,显然这和环有关,我们手写一下样例(样例真香)就可以发现每个点只有两种情况:

    1.在环中 这样的点答案为环的大小。

    2.通过一些点才能与环相连 这样的点答案为环的大小+到达环的最小距离

    于是我们就可以跑一遍tarjan,求出每个环的大小,对于那些不直接在环上的点,dfs一下即可。

    Code

     1 #include<cstdio>
     2 #
     3 include<algorithm>
     4 #include<stack>
     5 #define maxn 100090
     6 
     7 using namespace std;
     8 
     9 int n,x,tot,dfs_clock,scc_cnt;
    10 int head[maxn],dfn[maxn],scc[maxn],low[maxn],ans[maxn],size[maxn];
    11 struct node{
    12     int next,to;
    13 }edge[maxn];
    14 stack<int>s;
    15 
    16 void add(int x,int y)
    17 {
    18     edge[++tot].next=head[x];
    19     edge[tot].to=y;
    20     head[x]=tot;
    21 }
    22 
    23 void tarjan(int u)
    24 {
    25     dfn[u]=low[u]=++dfs_clock;
    26     s.push(u);
    27     for(int i=head[u];i;i=edge[i].next)
    28     {
    29         int v=edge[i].to;
    30         if(!dfn[v])
    31         {
    32             tarjan(v);
    33             low[u]=min(low[v],low[u]);
    34         }
    35         else if(!scc[v]) low[u]=min(low[u],dfn[v]);
    36     }
    37     if(dfn[u]==low[u])
    38     {
    39         scc_cnt++;
    40         while(1)
    41         {
    42             int p=s.top();
    43             s.pop();
    44             scc[p]=scc_cnt;
    45             if(u==p) break;
    46         }
    47     }
    48 }
    49 
    50 void dfs(int u,int fa,int step)
    51 {
    52     if(ans[fa])
    53     {
    54         ans[u]=ans[fa]+step;
    55         return ;
    56     }
    57     else dfs(u,edge[head[fa]].to,step+1);
    58 }
    59 
    60 int main()
    61 {
    62     scanf("%d",&n);
    63     for(int i=1;i<=n;i++)
    64     {
    65         scanf("%d",&x);
    66         add(i,x);
    67         if(i==x) ans[i]=1;
    68     }
    69     for(int i=1;i<=n;i++)
    70         if(!dfn[i]) tarjan(i);
    71     for(int i=1;i<=n;i++)
    72         size[scc[i]]++;
    73     for(int i=1;i<=n;i++)
    74         if(size[scc[i]]>1) ans[i]=size[scc[i]];
    75     for(int i=1;i<=n;i++)
    76         if(!ans[i]) dfs(i,edge[head[i]].to,1);
    77     for(int i=1;i<=n;i++)
    78         printf("%d
    ",ans[i]);
    79     return 0;
    80 }
    View Code

    然后就意想不到地RE了九个点(上述代码是AC的),查了大概两个小时(?),还一直以为是tarjan的锅,结果发现是Dfs的时候“else dfs(x,nxt[fa],step+1);”这句话,第二个参量应该是nxt[fa],我写成了nxt[x],这不就死循环了嘛。xswl。

    自己还是太菜了。(哭)

  • 相关阅读:
    隐马尔可夫模型 机器学习
    机器学习——EM算法与GMM算法
    机器学习——贝叶斯算法
    SVM算法 机器学习
    机器学习——谱聚类
    机器学习——Canopy算法
    机器学习——密度聚类
    Identity(身份)
    hyperledger fabric 结构模型学习
    fabric v1.1.0部署准备工作
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9520260.html
Copyright © 2011-2022 走看看