hiho1067(离线Tarjand)
题目链接:https://hihocoder.com/problemset/problem/1067
离线算法Tarjand。。。
参考:http://blog.csdn.net/tree__water/article/details/60965438
稍微加了点注释。
1 #include<cstdio> 2 #include<iostream> 3 #include<map> 4 #include<vector> 5 const int maxn=100010; 6 using namespace std; 7 string a,b; 8 9 map<string,int> pic; //将字符串映射成数字,便于后续操作 10 vector<int> edge[maxn],py[maxn],num[maxn]; 11 // 存边 查询关系 查询序号(离线之后按顺序输出用) 12 string trans[maxn]; //将数字转成对应的字符串 13 14 int vis[maxn]={0},in[maxn]={0},f[maxn]={0},ans[maxn]={0}; 15 // 入度 父亲 记录公共祖先序号 16 int gf(int x) 17 { 18 return x==f[x]?f[x]:f[x]=gf(f[x]); 19 } 20 21 void dfs(int u) 22 { 23 f[u]=u; 24 int len=edge[u].size(); 25 for(int i=0;i<len;i++) 26 { 27 dfs(edge[u][i]); 28 f[edge[u][i]]=u; 29 } 30 vis[u]=1; //子节点已全访问 31 len=py[u].size(); 32 for(int i=0;i<len;i++) //遍历相关的查询节点 33 { 34 if(vis[py[u][i]]) //如果访问过 35 ans[num[u][i]]=gf(py[u][i]); //找父亲 36 } 37 38 } 39 40 int main() 41 { 42 int n,m; 43 int cnt=0; 44 cin>>n; 45 while(n--) 46 { 47 cin>>a>>b; 48 if(!pic[a]) pic[a]=++cnt,trans[cnt]=a; //将字符串转成数字,并记录该数字对应的字符串 49 if(!pic[b]) pic[b]=++cnt,trans[cnt]=b; 50 int id1=pic[a]; 51 int id2=pic[b]; 52 in[id2]++; 53 edge[id1].push_back(id2); //加边 54 } 55 56 cin>>m; 57 for(int i=0;i<m;i++) 58 { 59 cin>>a>>b; 60 int id1=pic[a]; 61 int id2=pic[b]; 62 py[id1].push_back(id2); //记录查询关系 63 py[id2].push_back(id1); 64 num[id1].push_back(i); //记录输出顺序 65 num[id2].push_back(i); 66 } 67 for(int i=1;i<=cnt;i++) 68 if(in[i]==0) 69 dfs(i); 70 for(int i=0;i<m;i++) //桉顺序输出 71 cout<<trans[ans[i]]<<endl; 72 }