0294:Catch a Thief
問題文
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0294
解説
http://web-ext.u-aizu.ac.jp/pc-concours/2014/download/pastexam/editorial2013_final.pdf
私は書籍「最新コンパイラ構成技法」のLengauer-Tarjanの擬似コードを参考にしました。
#include<iostream> #include<vector> #include<algorithm> #include<cassert> #define max_v 100010 using namespace std; int dfnum[max_v]; int vertex[max_v]; int parent[max_v]; int ancestor[max_v]; int idom[max_v]; int semi[max_v]; int samedom[max_v]; int best[max_v]; vector<int>bucket[max_v]; vector<int>G[max_v],rG[max_v]; void dfs(int p, int n,int &k){ if(dfnum[n]==0 && !(n==0 && p>0)){ dfnum[n]=k; vertex[k++]=n; parent[n]=p; for(int i=0;i<G[n].size();i++){ dfs(n,G[n][i],k); } } } int ancestorWithLowestSemi(int v){ int a=ancestor[v]; if(ancestor[a]>0){ int b=ancestorWithLowestSemi(a); ancestor[v]=ancestor[a]; if(dfnum[semi[b]] < dfnum[semi[best[v]]])best[v]=b; } return best[v]; } void link(int p,int n){ ancestor[n]=p; best[n]=n; } void dominator(int sz,int root){ for(int i=0;i<sz;i++){ bucket[i].clear(); dfnum[i]=semi[i]=ancestor[i]=idom[i]=samedom[i]=0; } int N=0; dfs(0,root,N); for(int i=N-1;i>0;i--){ int n=vertex[i],p=parent[n],s=p; for(int j=0;j<rG[n].size();j++){ int v=rG[n][j],s1; if(dfnum[v]<=dfnum[n])s1=v; else s1=semi[ancestorWithLowestSemi(v)]; if(dfnum[s1]<dfnum[s])s=s1; } semi[n]=s; bucket[s].push_back(n); link(p,n); for(int j=0;j<bucket[p].size();j++){ int v=bucket[p][j],y=ancestorWithLowestSemi(v); if(semi[y]==semi[v])idom[v]=p; else samedom[v]=y; } bucket[p].clear(); } for(int i=1;i<N;i++){ int n=vertex[i]; if(samedom[n]>0){ idom[n]=idom[samedom[n]]; } } for(int i=1;i<N;i++){ for(int j=0;j<rG[i].size();j++){ if(rG[i][j]==root)idom[i]=0; } } } int main(void){ int n,m; cin >> n >> m; for(int i=0;i<m;i++){ int s,t; cin >> s >> t; s--,t--; G[s].push_back(t); rG[t].push_back(s); } dominator(n,0); int q,r; cin >> q; while(q--){ cin >> r; r--; if(idom[r]==0)cout << r+1 << endl; else cout << idom[r]+1 << endl; } return 0; }