BZOJ3887: [Usaco2015 Jan]Grass Cownoisseur

Posted Blue233333

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",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

 

以上是关于BZOJ3887: [Usaco2015 Jan]Grass Cownoisseur的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3887: [Usaco2015 Jan]Grass Cownoisseur

tarjan+拓扑BZOJ3887-[Usaco2015 Jan]Grass Cownoisseur

线段树 BZOJ3888 [Usaco2015 Jan]Stampede

bzoj3886:[Usaco2015 Jan]Moovie Mooving

BZOJ-3890: [Usaco2015 Jan]Meeting Time (背包DP)

bzoj3886: [Usaco2015 Jan]Moovie Mooving