hdu2586How far away ?-(LCA)
作者:互联网
http://acm.hdu.edu.cn/showproblem.php?pid=2586
题意:有n个点,有n-1条线连通,求两点间的最短距离,最近公共祖先的入门题。Tarjan离线算法。
#include<stdio.h> #include<iostream> #include<algorithm> #include<cstring> #include<math.h> #include<string> #include<queue> #define ll long long #define inf 0x3f3f3f3f using namespace std; int t; int n,m; int x,y,z; bool vis[40005];///深搜过程判断是否被搜过 int par[40005];///存储节点的父亲 int dis[40005];///任意一点到搜索起始点的距离 int ans[205]; struct node1 { int to; int val; }; vector<node1>edge[40005];///邻接表存储边 struct node2 { int to; int idx;///第几个查询 }; vector<node2>que[40004];///邻接表存储查询 void init() { memset(dis,0,sizeof(dis)); memset(vis,false,sizeof(vis)); for(int i=1;i<=n;i++) { edge[i].clear(); que[i].clear(); par[i]=i; } } int find(int x)///并查集找爹 { if(par[x]==x) return x; else return par[x]=find(par[x]); } void unit(int x,int y)///认x做父亲 { x=find(x); y=find(y); if(x!=y) par[y]=x; } void dfs(int now,int w)///now是当前点,w是到起始点的距离 { vis[now]=true; dis[now]=w; int len1=edge[now].size(); for(int i=0;i<len1;i++) { int temp=edge[now][i].to;///临时存储邻接点,简洁表示 if( !vis[ temp ] ) { dfs( temp,w+edge[now][i].val ); unit(now,temp);///搜完才更新父节点 } } int len2=que[now].size(); for(int i=0;i<len2;i++)///看一下有没有 与 当前点 有询问关系的点 { int temp=que[now][i].to; if( vis[ temp ] ) { ans[ que[now][i].idx ] = dis[now]+dis[temp]-2*dis[ find(temp) ]; ///两点的最短距离 = 两点到起点的距离之和 - 两倍公共祖先到起点的距离 } } } int main() { scanf("%d",&t); while(t--) { scanf("%d %d",&n,&m); init(); for(int i=1;i<n;i++) { scanf("%d%d%d",&x,&y,&z); edge[x].push_back( {y,z} ); edge[y].push_back( {x,z} ); } for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); que[x].push_back( {y,i} ); que[y].push_back( {x,i} ); } dfs(1,0);///以1为起始点深搜 for(int i=1;i<=m;i++) printf("%d\n",ans[i]); } return 0; }
标签:hdu2586How,存储,vis,far,away,int,40005,include,dis 来源: https://www.cnblogs.com/shoulinniao/p/10783254.html