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 }