hdu 4547 CD操作 【tarjan的LCA操作+map】
阿新 • • 發佈:2018-12-07
題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=4547
思路:由於點很多所以需要鄰接表存資料,先dfs記錄每個點的深度,然後tarjan找到最近共公祖先,然後根據題意輸出
這到題需要map來講字串轉換成數字來記錄;
父目錄到子目錄只需一步,子目錄到父目錄所需步數就是深度差,轉成的目錄不是父目錄那麼轉成另一目錄的步數就是到兩者最近公共祖先的深度的差再加一,否則不用加。而如果兩者是一樣的,也就是它要轉成它自己,那麼所需的步數就是0.
#include<stdio.h> #include<string.h> #include<string> #include<queue> #include<stack> #include<map> #include<vector> #include<set> #include<algorithm> #define inf 0x3f3f3f3f using namespace std; const int N=4e5+10; struct node { int v,ne; }edge[N]; int head[N]; struct node1//存查詢的路徑 { int v,ne,num; }qre[N]; int f[N]; struct node2//存查詢的點和他們的最先公共祖先 { int v,u,lca; }ans[N]; int vis[N];//標記是否訪問 int deep[N];//記錄深度 int pre[N]; int isroot[N];//找根 int n,e,m,top; map<string,int>mp;//把字串轉換成數字 void add(int a,int b) { edge[e].v=b; edge[e].ne=head[a]; head[a]=e++; } void addq(int a,int b,int c) { qre[e].v=b; qre[e].ne=f[a]; qre[e].num=c; f[a]=e++; } void init() { top=0; memset(f,-1,sizeof(f)); memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); memset(deep,0,sizeof(deep)); for(int i=1;i<=n;i++) pre[i]=i; } void dfs(int a)//dfs訪問每個點並記錄深度 { for(int i=head[a];i!=-1;i=edge[i].ne) { int v=edge[i].v; if(!deep[v]) { deep[v]=deep[a]+1; dfs(v); } } } int found(int r)//找祖先並且壓縮路徑 { if(r==pre[r]) return r; else { pre[r]=found(pre[r]); return pre[r]; } } int change(char str[]) { if(mp.find(str)==mp.end()) { mp[str]=++top; return top; } else return mp[str]; } void tarjan(int u) { for(int i=f[u];i!=-1;i=qre[i].ne) { int v=qre[i].v; if(vis[v]) { int temp=qre[i].num; ans[temp].lca=found(v); } } vis[u]=1; for(int i=head[u];i!=-1;i=edge[i].ne) { int v=edge[i].v; if(!vis[v]) { tarjan(v); pre[v]=u; } } } void solve() { for(int i=1;i<=n;i++) { if(!isroot[i]) { deep[i]=1; dfs(i); tarjan(i); } } } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d %d",&n,&m); int a,b; init(); memset(isroot,0,sizeof(isroot)); mp.clear(); char str1[45],str2[45]; e=0; for(int i=1;i<=n-1;i++) { scanf("%s",str1); scanf("%s",str2); a=change(str1); b=change(str2); add(a,b); add(b,a); isroot[a]=1; } e=0; for(int i=1;i<=m;i++) { scanf("%s",str1); scanf("%s",&str2); a=mp[str1]; b=mp[str2]; addq(a,b,i); addq(b,a,i); ans[i].u=a; ans[i].v=b; } solve(); for(int i=1;i<=m;i++) { int t=deep[ans[i].u]-deep[ans[i].lca]; if(ans[i].v!=ans[i].lca) t++; if(ans[i].v==ans[i].u) t=0; printf("%d\n",t); } } return 0; }