/* 在我还不知道LCA之前 暴力跑的SPFA 70分 三个点TLE */ #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; struct node { int u; int t; int pre; }; node a[30010*2+100]; queue<int>q; int n,qq,x[30010],num,head[30010],f[30010],dis[30010],sum; void add(int from,int to) { num++; a[num].pre=head[from]; a[num].u=to; a[num].t=1; head[from]=num; } void SPFA() { int i,j; for(j=1;j<=qq-1;j++) { memset(dis,127/3,sizeof(dis)); memset(f,0,sizeof(f)); int s=x[j]; int v=x[j+1]; q.push(s); f[s]=1; dis[s]=0; do { int k=q.front(); q.pop(); f[k]=0; for(i=head[k];i;i=a[i].pre) { if(dis[a[i].u]>dis[k]+a[i].t) { dis[a[i].u]=dis[k]+a[i].t; if(f[a[i].u]==0) { q.push(a[i].u); f[a[i].u]=1; } } } }while(!q.empty()); sum=sum+dis[v]; } } int main() { int i,o,u; cin>>n; for(i=1;i<=n-1;i++) { cin>>o>>u; add(o,u); add(u,o); } cin>>qq; for(i=1;i<=qq;i++) cin>>x[i]; SPFA(); cout<<sum; }
/* 倍增LCA 将旅行路线两两拆开 求相邻两点的距离 即求他们到lca的距离和 这里用倍增法实现求距离 fa[i][j]表示i节点往上2^j层的节点是什么 因为1 2 4 8 16...做和可以表示所有的整数 所以保证覆盖整张图 先Dfs建图 顺面几下每个节点的所在层 以及fa[i][0] 的值 然后DP预处理fa数组 然后就是求到lca的距离了 这里我们求出只需要求出lca是谁 那么两点之间的最小距离就是 deep[p1]+deep[p2]-2*deep[anc] deep是深度 剩下的就仅仅是找lca是谁了 对于一组a ,b 如果他们在同一层的话 我们只需要同时向上移动他俩 知道a==b */ #include<iostream> #include<cstdio> #include<cstring> #define maxn 30010 #define S 16 int n,m,num,head[maxn],fa[maxn][S+5],deep[maxn],p1,p2,ans; struct node { int u,v,pre; }e[maxn*2]; void Add(int from,int to) { num++; e[num].u=from; e[num].v=to; e[num].pre=head[from]; head[from]=num; } void swap(int &a,int &b) { int t=a;a=b;b=t; } void init() { scanf("%d",&n); int x,y; for(int i=1;i<=n-1;i++) { scanf("%d%d",&x,&y); Add(x,y);Add(y,x); } } void get_fa() { for(int j=1;j<=S;j++) for(int i=1;i<=n;i++) fa[i][j]=fa[fa[i][j-1]][j-1];//数学方法展开就是fa[i][j] } void Dfs(int now,int from,int c)//得带每个点的所在层 { fa[now][0]=from; deep[now]=c; for(int i=head[now];i;i=e[i].pre) if(e[i].v!=from) Dfs(e[i].v,now,c+1); } int get_same(int a,int t)//计算a往上t层是啥 { for(int i=1;i<=t;i++) a=fa[a][0]; return a; } int LCA(int a,int b) { if(deep[a]<deep[b])swap(a,b);//保证a深度大 a=get_same(a,deep[a]-deep[b]);//得到a向上deep[a]-deep[b]层是谁 即a的与b同层的祖先是谁 if(a==b)return a;//如果汇聚到一个点 就不用往上了 for(int i=S;i>=0;i--)//这里有套路 从最大值开始循环 一开始 fa[a][i] fa[b][i]一定是相等的 //因为此时位于他们lca之上 然后往下 这里可以覆盖每一层 if(fa[a][i]!=fa[b][i]) { a=fa[a][i]; b=fa[b][i]; } return fa[a][0]; } int main() { init(); Dfs(1,1,0); get_fa(); scanf("%d%d",&m,&p1); for(int i=1;i<=m-1;i++) { scanf("%d",&p2); int anc=LCA(p1,p2); ans+=deep[p1]+deep[p2]-2*deep[anc]; p1=p2; } printf("%d ",ans); return 0; }