//usage: ./LinearVEogdf #include #include #include #include using namespace std::chrono; using namespace ogdf; int n, m; int* edges; Graph G; NodeArray> Adj; void compute_count(); int* count; NodeArray dfs; node* idfs; NodeArray> T; NodeArray p, l, low, highp, M, Mp, tempChild; NodeArray bcount, up; NodeArray> invM, invMp, invHighp; void compute_M(); void compute_highp(); void sort_ChildrenHighp(); NodeArray ufparent, representative; NodeArray ufrank; void ufInit(); node find(node); void unite(node,node,node); int main(int n_args, char** args) { /* read graph from file */ FILE* fp = fopen(args[1],"r"); fscanf(fp,"%d %d",&n,&m); node* vertex = new node[n]; for(int i=0;isucc()) { node x = e->source(); node y = e->target(); Adj[x].pushBack(y); Adj[y].pushBack(x); } compute_count(); high_resolution_clock::time_point t2 = high_resolution_clock::now(); duration time_span = duration_cast>(t2 - t1); printf("%f\n",time_span.count()); fp = fopen(args[2],"w"); for(int i=0;isucc()){dfs[v]=-1;} //initialize tempChild.init(G); l.init(G); low.init(G); bcount.init(G); up.init(G); for(node v=G.firstNode(); v!=nullptr; v=v->succ()) { l[v]=v; low[v]=v; bcount[v]=0; up[v]=0; } node* temp_vertex = new node[n]; ListIterator* temp_out = new ListIterator[n]; int Nr=0; //current DFS label dfs[r]=Nr; idfs[Nr++]=r; p[r]=nullptr; temp_vertex[0]=r; temp_out[0]=Adj[r].begin(); int SP=0; //perform DFS while(SP!=-1) { node v=temp_vertex[SP]; char descend=0; for(ListIterator i=temp_out[SP]; i!=Adj[v].end(); i++) { node u = *i; if(dfs[u]==-1) { dfs[u]=Nr; idfs[Nr++]=u; p[u]=v; T[v].pushBack(u); tempChild[v]=u; temp_vertex[SP+1]=u; temp_out[SP+1]=Adj[u].begin(); temp_out[SP]=i; descend=1; break; } if(dfs[u]index()]+=bcount[v]==1; } //high(u)=v for(node v=G.firstNode(); v!=nullptr; v=v->succ()) { ListIterator u = invHighp[v].begin(); ListIterator c = T[v].begin(); while(u.valid()) { if(up[*u]!=0){u++;continue;} //check if high(u)=highp(u) while(!(*c==T[v].back() || dfs[*(c.succ())]>dfs[*u])) { c++; } if(low[*u]==v || dfs[*u]<=dfs[Mp[*c]] ) { count[v->index()]++; } u++; } } //high(u)succ()) { ListIterator u = invM[x].begin(); ListIterator c = invMp[x].begin(); while(u.valid() && c.valid()) { while(c.valid() && dfs[*c]>=dfs[*u]){c++;} if(!c.valid()){break;} if(up[*u]==0 && dfs[highp[*u]]index()]+=n_edges; c++; } } else { u++; } } } //M(u)=v sort_ChildrenHighp(); //sort the lists of children in decreasing order w.r.t. the highp of their elements for(node v=G.firstNode(); v!=nullptr; v=v->succ()) { if(invM[v].size()==0){continue;} ListIterator u = invM[v].begin(); u++; ListIterator c = T[v].begin(); node min=v; while(u.valid() && c.valid()) { min=highp[*c]; while(u.valid() && dfs[*u]>dfs[min]) { count[v->index()]++; u++; } min=low[*c]; c++; while(c.valid() && dfs[highp[*c]]>=dfs[min]) { if(dfs[low[*c]]dfs[min]){u++;} } while(u.valid()) { if(dfs[*u]<=dfs[min]) { count[v->index()]++; } u++; } } //M(u)>v for(node x=G.firstNode(); x!=nullptr; x=x->succ()) { ListIterator c = invMp[x].begin(); ListIterator u = invM[x].begin(); while(c.valid() && u.valid()) { while(u.valid() && dfs[*u]>=dfs[p[*c]]){u++;} if(!u.valid()){break;} if(dfs[highp[*c]] first = u; ListIterator last; while(u.valid() && dfs[highp[*c]]index()]+=n_edges; c++; while(c.valid() && dfs[*last]=dfs[p[*c]]) { n_edges--; first++; } count[p[*c]->index()]+=n_edges; c++; } } else { c++; } } } } //computes M, Mp, invM, and invMp void compute_M() { M.init(G); Mp.init(G); for(node v=G.firstNode(); v!=nullptr; v=v->succ()){M[v]=nullptr;Mp[v]=nullptr;} NodeArray> L; NodeArray> R; L.init(G); R.init(G); NodeArray setL; setL.init(G); for(node v=G.firstNode(); v!=nullptr; v=v->succ()){setL[v]=0;} //begin computation, in a bottom-up fashion //for M, ignore the root; for Mp, ignore the child of the root as well for(int i=n-1;i>0;i--) { node v=idfs[i]; //i = dfs[v] //fix the pointers L and R for(ListIterator cIndx=T[v].begin(); cIndx!=T[v].end(); cIndx++) { node c = *cIndx; //c is a child of v if(dfs[low[c]]=i){L[d]++;} while(dfs[low[*R[d]]]>=i){R[d]--;} if(L[d]!=R[d]){M[v]=d;break;} d=M[*L[d]]; } } if(i==1){break;} //v is the child of the root int dfsP = dfs[p[v]]; //find Mp[v] if(dfs[l[v]]=dfsP){L[v]++;} while(dfs[low[*R[v]]]>=dfsP){R[v]--;} if(L[v]!=R[v]){Mp[v]=v;continue;} else { node d=Mp[*L[v]]; while(1) { if(dfs[l[d]]=dfsP){L[d]++;} while(dfs[low[*R[d]]]>=dfsP){R[d]--;} if(L[d]!=R[d]){Mp[v]=d;break;} d=Mp[*L[d]]; } } } //calculate the inverse lists, and have their elements sorted in decreasing order invM.init(G); for(int i=n-1;i>0;i--) { node v=idfs[i]; invM[M[v]].pushBack(v); } invMp.init(G); for(int i=n-1;i>1;i--) { node v=idfs[i]; invMp[Mp[v]].pushBack(v); } //delete[] L; delete[] R; delete[] invMnext; } void compute_highp() { highp.init(G); ufInit(); for(int i=n-1;i>=0;i--) { node v=idfs[i]; for(ListIterator j=Adj[v].begin(); j!=Adj[v].end(); j++) { node u=*j; if(dfs[v]succ()) { T[v].clear(); } for(int i=n-1; i>-1; i--) { node x=idfs[i]; List temp; for(ListIterator c = invHighp[x].begin(); c.valid(); c++) { temp.pushFront(*c); } for(ListIterator c = temp.begin(); c.valid(); c++) { T[p[*c]].pushBack(*c); } } //delete[] TnextChild; } void ufInit() { ufparent.init(G); ufrank.init(G); representative.init(G); for (node v=G.firstNode(); v!=nullptr; v=v->succ()) { ufparent[v] = representative[v] = v; ufrank[v] = 0; } } node find(node x) { node r=x; while(ufparent[r]!=r){r=ufparent[r];} while(ufparent[x]!=x){node next=ufparent[x]; ufparent[x]=r; x=next;} return r; } void unite(node x, node y, node w) { node r1=find(x); node r2=find(y); if(r1==r2){representative[r1]=w;return;} int cmp=ufrank[r1]-ufrank[r2]; if(cmp<0) { ufparent[r1]=r2; representative[r2]=w; } else if(cmp>0) { ufparent[r2]=r1; representative[r1]=w; } else { ufparent[r1]=r2; ufrank[r2]++; representative[r2]=w; } }