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 }
以上是关于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