Advertising:
#include <stdio.h>int main(){ puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44081931");}
Test instructions
Give a directed graph and choose a path with a path starting point of 1, and one chance to go in the opposite direction of a certain edge, and ask how many points can be passed? (a point in the path, no matter how manytimes ( ≥ 1) The contribution to the answer is 1)
Exercises
First, the strongly connected component shrinks.
The DFS statistics are then formed:
Set A: Point 1 To what point,
Set B: Which points can point to 1
The two collections are then each topology diagram.
Now a longest path that starts from 1 and then goes back to 1 can be represented as the longest chain in 1~a, a longest chain in a point A and a point in the 1~b, which is returned directly to a point B in set B by the reverse edge.
Code:
#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 501000using namespace STD;structksd{intV,next;BOOL operator< (ConstKSD &a)Const{returnV==A.V?NEXT<A.NEXT:V<A.V;}} E[n],e[n],rd[n];inthead[n],head[n],cnt;inline voidAddintUintV) {e[++cnt].v=v; E[cnt].next=head[u]; head[u]=cnt;}inline voidADD (intUintV) {e[++cnt].v=v; E[cnt].v=u; E[cnt].next=head[u]; E[CNT].NEXT=HEAD[V]; head[v]=head[u]=cnt;}//Pinch pointBOOLDe[n];intNum[n],n,m;structtarjan_2_3_3_3{intDfn[n],cnt,vis[n],id[n];voidDFS1 (intx) {vis[x]=1;intI,v; for(I=head[x];i;i=e[i].next)if(!VIS[V=E[I].V]) DFS1 (v); Dfn[++cnt]=x; }voidDFS2 (intXintGroup) {intI,v; Id[x]=group; for(I=head[x];i;i=e[i].next)if(!ID[V=E[I].V]) DFS2 (V,group); }voidWorkintN) {//Kosaraju for(intI=1; i<=n;i++)if(!vis[i]) DFS1 (i); for(inti=n;i;i--)if(!id[dfn[i]]) DFS2 (Dfn[i],dfn[i]); for(intI=1; i<=n;i++) num[id[i]]++;//Go to heavy side for(intI=1; i<=m;i++) {RD[I].V=ID[RD[I].V]; Rd[i].next=id[rd[i].next]; } sort (rd+1, rd+m+1); for(intI=1; i<=m;i++) {if(rd[i].v==rd[i-1].v&&rd[i].next==rd[i-1].next) de[i]=1;Else if(Rd[i].v==rd[i].next) de[i]=1; }}}suodian;BOOLVis1[n],vis2[n];//Judge 1 to which points, which points can be to 1voidDFS1 (intx) {vis1[x]=1;intI,v; for(I=head[x];i;i=e[i].next) {if(VIS1[V=E[I].V])Continue; DFS1 (v); }}voidDFS2 (intx) {vis2[x]=1;intI,v; for(I=head[x];i;i=e[i].next) {if(VIS2[V=E[I].V])Continue; DFS2 (v); }}intF1[n],f2[n],d[n]; Queue<int>QintMain () {Freopen ("Test1.in","R", stdin);intI,j,k;intb;scanf("%d%d", &n,&m); for(i=1; i<=m;i++) {scanf("%d%d", &rd[i].v,&rd[i].next); ADD (Rd[i].v,rd[i].next); } DFS1 (1), DFS2 (1); Suodian.work (n);//Handle 1 points that can be reached memset(Head,0,sizeofHead), cnt=0;memset(d,0,sizeofD); for(i=1; i<=m;i++)if(!de[i]) {a=rd[i].v,b=rd[i].next;if(Vis1[a]&vis1[b]) Add (A, b), d[b]++; } while(!q.empty ()) Q.pop (); Q.push (1); while(!q.empty ()) {A=q.front (), Q.pop (); F1[a]+=num[a]; for(I=head[a];i;i=e[i].next) {d[b=e[i].v]--; F1[b]=max (F1[b],f1[a]);if(!d[b]) Q.push (b); } }//processing can be up to 1 points memset(Head,0,sizeofHead), cnt=0;memset(d,0,sizeofD); for(i=1; i<=m;i++)if(!de[i]) {a=rd[i].v,b=rd[i].next;if(Vis2[a]&vis2[b]) Add (b,a), d[a]++; } while(!q.empty ()) Q.pop (); Q.push (1); while(!q.empty ()) {A=q.front (), Q.pop (); F2[a]+=num[a]; for(I=head[a];i;i=e[i].next) {d[b=e[i].v]--; F2[b]=max (F2[b],f2[a]);if(!d[b]) Q.push (b); } }//Enumerate edges intans=2*num[1]; for(i=1; i<=m;i++)if(!de[i]) {a=rd[i].next,b=rd[i].v;if(Vis1[a]&&vis2[b]) Ans=max (ans,f1[a]+f2[b]); }printf("%d\n", ans-num[1]);return 0;}
"BZOJ3887" "Usaco2015 Jan" Grass cownoisseur algorithm module a bit more