传送门
题意:就是一棵树,求节点距离。
思路:如果t是u,v的最近公共祖先,那么d[u,v]=d[u,root]+d[v,root]-2*d[t,root],就根据这个来搞之。
每到一个点然后遍历所有询问。。。果断超了,之后便用vector来存询问,也超时,然后find函数压缩了下路径就过了。。。。。。。
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; struct node { int v,w; node(){}; node(int a,int b){v=a;w=b;} }; vector<node>e[40005],q[150000]; int m,n,k,d[40005],f[40005],ans[150000]; bool vis[40005]; char str[5]; int find(int x) { if(f[x]==x)return x; else { f[x]=find(f[x]); return f[x]; } } void LCA(int u,int dis) { int v; vis[u]=1; d[u]=dis; f[u]=u; int size=e[u].size(); for(int i=0;i<size;i++) { v=e[u][i].v; if(!vis[v]) { LCA(v,dis+e[u][i].w); f[v]=u; } } size=q[u].size(); for(int i=0;i<size;i++) { v=q[u][i].v; if(vis[v]) { ans[q[u][i].w]=d[u]+d[v]-2*d[find(v)]; } } } int main() { int u,v,w; scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { scanf("%d%d%d%s",&u,&v,&w,str); node temp1(v,w); node temp2(u,w); e[u].push_back(temp1); e[v].push_back(temp2); } scanf("%d",&k); for(int i=0;i<k;i++) { scanf("%d%d",&u,&v); node temp1(v,i); node temp2(u,i); q[u].push_back(temp1); q[v].push_back(temp2); } memset(vis,0,n+1); LCA(1,0); for(int i=0;i<k;i++)printf("%d\n",ans[i]); return 0; }