zoukankan      html  css  js  c++  java
  • BZOJ3887: [Usaco2015 Jan]Grass Cownoisseur

    n<=100000个点m<=100000条边有向图,有一次机会沿着某条边反方向走一次,求从一号点出发最终到达一号点的路径经过的不同的点的数量的最大值。

    tarjan缩完点,如果没机会反方向的话答案就是1所在的分量的大小。现在有了,其实就是1->1能到达的某个点->反向边->能到达1的某个点,所以只要知道1的分量到达每个分量的最多点数,以及每个分量到1的分量的经过最多点数,最后枚举边计算答案即可。这个经过最多点数,可以按拓扑序DP。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stdlib.h>
     4 #include<algorithm>
     5 //#include<queue>
     6 #include<iostream>
     7 using namespace std;
     8 
     9 int n,m;
    10 #define maxn 100011
    11 #define maxm 200011
    12 int Time=0,dfn[maxn],low[maxn],bel[maxn],sta[maxn],top=0,tot=0,cnt[maxn];bool insta[maxn];
    13 struct Edge{int to,next;};
    14 const int inf=0x3f3f3f3f;
    15 struct Graph
    16 {
    17     Edge edge[maxm];int first[maxn],le,ind[maxn],f[maxn];
    18     Graph() {memset(first,0,sizeof(first));le=2;}
    19     void in(int x,int y) {Edge &e=edge[le];e.to=y;e.next=first[x];first[x]=le++;}
    20     int que[maxn],head,tail;
    21     void topo()
    22     {
    23         head=tail=0;
    24         for (int i=1;i<=tot;i++) if (!ind[i]) que[tail++]=i;
    25         for (int i=1;i<=tot;i++) f[i]=-inf;f[bel[1]]=0;
    26         while (head!=tail)
    27         {
    28             const int now=que[head++];
    29 //            cout<<now<<":)";
    30             f[now]+=cnt[now];
    31             for (int i=first[now];i;i=edge[i].next)
    32             {
    33                 const Edge &e=edge[i];
    34                 f[e.to]=max(f[e.to],f[now]);
    35                 ind[e.to]--;
    36                 if (!ind[e.to]) que[tail++]=e.to;
    37             }
    38         }
    39     }
    40 }g,gg,ggg;
    41 void tarjan(int x,int fa)
    42 {
    43     low[x]=dfn[x]=++Time;
    44     sta[++top]=x;insta[x]=1;
    45     for (int i=g.first[x];i;i=g.edge[i].next)
    46     {
    47         const Edge &e=g.edge[i];
    48         if (!dfn[e.to]) tarjan(e.to,x),low[x]=min(low[x],low[e.to]);
    49         else if (insta[e.to]) low[x]=min(low[x],dfn[e.to]);
    50     }
    51     if (dfn[x]==low[x])
    52     {
    53         tot++;
    54         while (sta[top]!=x) bel[sta[top]]=tot,cnt[tot]++,insta[sta[top--]]=0;
    55         bel[sta[top]]=tot,cnt[tot]++,insta[sta[top--]]=0;
    56     }
    57 }
    58 int ans=0;
    59 void tarjan()
    60 {
    61     memset(dfn,0,sizeof(dfn));
    62     for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i,0);
    63     for (int i=1;i<=n;i++)
    64         for (int j=g.first[i];j;j=g.edge[j].next)
    65         {
    66             const Edge &e=g.edge[j];
    67             if (bel[i]!=bel[e.to])
    68             {
    69                 gg.in(bel[i],bel[e.to]);
    70                 gg.ind[bel[e.to]]++;
    71                 ggg.in(bel[e.to],bel[i]);
    72                 ggg.ind[bel[i]]++;
    73             }
    74         }
    75     gg.topo();ggg.topo();
    76     int ans=cnt[bel[1]];
    77     for (int i=2;i<gg.le;i++)
    78     {
    79         const int a=gg.edge[i].to,b=ggg.edge[i].to;
    80         ans=max(ans,ggg.f[b]+gg.f[a]-cnt[bel[1]]);
    81     }
    82     printf("%d
    ",ans);
    83 }
    84 void init()
    85 {
    86     scanf("%d%d",&n,&m);int x,y;
    87     for (int i=1;i<=m;i++)
    88     {
    89         scanf("%d%d",&x,&y);
    90         g.in(x,y);
    91     }
    92 }
    93 int main()
    94 {
    95     init();
    96     tarjan();
    97     return 0;
    98 }
    View Code
  • 相关阅读:
    .NET 环境中使用RabbitMQ
    WPF窗口模板——Style样式
    C#获取当前日期时间
    C#解析JSON字符串总结
    c#简单加密和对称加密
    List<T>转换为二维数组
    java后台导出pdf
    C# 创建 读取 更新 XML文件
    python 第三天
    编写登录接口
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7604808.html
Copyright © 2011-2022 走看看