1. 程式人生 > >學習LCA( 最近公共祖先·二)

學習LCA( 最近公共祖先·二)

dex node int 離線 i++ cout com ans pan

http://hihocoder.com/problemset/problem/1067

tangin+離線

#include<bits/stdc++.h>
using namespace std;
const int M=1e5+10;
struct node{
    int to,index;
    node (int v,int index){
        this->to=v;
        this->index=index;
    }
};
vector<int>graph[M];
vector<node>e[M];
bool sign[M]; map<int,string>str; map<string,int>indx; int ans[M]; int f[M],color[M]; int tot,n,m,root; void init(){ tot=0; indx.clear(); memset(sign,false,sizeof(sign)); memset(color,0,sizeof(color)); memset(ans,0,sizeof(ans)); for(int i=0;i<M;i++){ graph[i].clear(); e[i].clear(); f[i]
=i; } } int find(int x){ return x==f[x]?x:f[x]=find(f[x]); } int get_index(string x){ if(indx.count(x)) return indx[x]; indx[x]=++tot; str[tot]=x; return tot; } void input(){ cin>>n; for(int i=1;i<=n;i++){ string name1,name2; cin
>>name1>>name2; int a=get_index(name1); int b=get_index(name2); graph[a].push_back(b); sign[b]=true; } cin>>m; for(int i=1;i<=m;i++){ string name1,name2; cin>>name1>>name2; int a=get_index(name1); int b=get_index(name2); e[a].push_back(node(b,i)); e[b].push_back(node(a,i)); } } void targin(int u){ color[u]=1; for(int i=0;i<e[u].size();i++){ int ID=e[u][i].index; if(ans[ID]) continue; int v=e[u][i].to; if(color[v]==0) //0代表v未訪問過 continue; if(color[v]==1) //1代表正在訪問,所以u和v的最近公共祖先就是v ans[ID]=v; if(color[v]==2) //2代表訪問完畢的點,所以u和v的最近公共祖先就是v當前的祖先 ans[ID]=find(v); } for(int i=0;i<graph[u].size();i++){ int v=graph[u][i]; targin(v); //一個節點dfs完後,標記vv為訪問完畢的點,並更新父節點 color[v]=2; f[v]=u; } } void solve(){ for(int i=1;i<=n;i++) if(!sign[i]) root=i; targin(root); for(int i=1;i<=m;i++) cout<<str[ans[i]]<<endl; } int main(){ init(); input(); solve(); return 0; }

學習LCA( 最近公共祖先·二)