//usage: ./LinearVE #include #include #include int n, m; int* edges; int* G; int* firstOut; void create_adj(); void compute_count(); int* count; int* dfs, * idfs, * parent, * T, * firstChild, * tempChild; int* l, * low, * highp, * bcount, * up, * L, * R, * M, * Mp; int* invHighp, * firstInvHighp; int* invM, * invMfirst, * invMp, * invMpfirst; void construct_tree(); void compute_M(); void computeInvM(); void compute_highp(); void sort_ChildrenHighp(); int* ufparent, * ufrank, * representative; void ufInit(); int find(int); void unite(int, int, int); int main(int n_args, char** args){ FILE* fp = fopen(args[1], "r"); fscanf(fp, "%d %d", &n, &m); edges = (int*)malloc(sizeof(int)*2*m); for(int i=0;i0){ u++;continue; } //check if high(u)=highp(u) while(!(c==endT-1 || dfs[T[c+1]]>dfs[invHighp[u]])){ c++; } if(low[invHighp[u]]==v || dfs[invHighp[u]]<=dfs[Mp[T[c]]]){ count[v]++; } u++; } } //high(u)=dfs[invM[u]]){ c++; } if(c==endMp){ break; } if(up[invM[u]]==0 && dfs[highp[invM[u]]]dfs[min]){ count[v]++; u++; } min=low[T[c]]; c++; while(c!=endT && dfs[highp[T[c]]]>=dfs[min]){ if(dfs[low[T[c]]]dfs[min]){ u++; } } while(u!=endM){ if(dfs[invM[u]]<=dfs[min]){ count[v]++; } u++; } } //M(u)>v for(int x=0;x=dfs[parent[invMp[c]]]){ u++; } if(u==endM){ break; } if(dfs[highp[invMp[c]]]=dfs[parent[invMp[c]]]){ n_edges--; first++; } count[parent[invMp[c]]]+=n_edges; c++; } } else{ c++; } } } } void construct_tree(){ //sort the list of the children of every vertex in increasing order T = (int*)malloc(sizeof(int)*n); firstChild = (int*)malloc(sizeof(int)*(n+1)); for(int i=0;i<=n;i++){ firstChild[i]=0; } for(int i=1;i0;i--){ int v=idfs[i]; //initialize L and R to calculate M[v] L[v]=firstChild[v]; R[v]=firstChild[v+1]-1; //compute M if(dfs[l[v]]=dfs[v]){ L[m]++; } while(dfs[low[T[R[m]]]]>=dfs[v]){ R[m]--; } if(L[m]!=R[m]){ M[v]=m;break; } c=T[L[m]]; m=M[c]; } } if(i==1){ break; } //Mp is undefined for the child of the root //compute Mp if(dfs[l[v]]=dfs[parent[v]]){ L[v]++; } while(dfs[low[T[R[v]]]]>=dfs[parent[v]]){ R[v]--; } if(L[v]!=R[v]){ Mp[v]=v; } else{ int c=T[L[v]]; int m=Mp[c]; while(1){ if(dfs[l[m]]=dfs[parent[v]]){ L[m]++; } while(dfs[low[T[R[m]]]]>=dfs[parent[v]]){ R[m]--; } if(L[m]!=R[m]){ Mp[v]=m;break; } c=T[L[m]]; m=Mp[c]; } } } } void computeInvM(){ //calculate the inverse lists, and have their elements sorted in decreasing order invM = new int[n]; invMfirst = new int[n+1]; for(int i=0;i<=n;i++){ invMfirst[i]=0; } for(int i=1;i0;i--){ int v=idfs[i]; invM[invMnext[M[v]]++]=v; } invMp = new int[n]; invMpfirst = new int[n+1]; for(int i=0;i<=n;i++){ invMpfirst[i]=0; } for(int i=2;i1;i--){ int v=idfs[i]; invMp[invMnext[Mp[v]]++]=v; } } void compute_highp(){ highp = (int*)malloc(sizeof(int)*n); ufInit(); for(int i=n-1;i>=0;i--){ int v=idfs[i]; for(int j=firstOut[v];j=0;i--){ int v=idfs[i]; for(int i=firstInvHighp[v];i0){ ufparent[r2]=r1; representative[r1]=w; } else{ ufparent[r1]=r2; ufrank[r2]++; representative[r2]=w; } } void create_adj(){ G = (int*)malloc(sizeof(int)*4*m); firstOut = (int*)malloc(sizeof(int)*(n+1)); for(int i=0;i<=n;i++){ firstOut[i]=0; } for(int i=0;i