poj 1968 Distance Queries LCA Tarjan 离线算法
2014-02-12 14:10
453 查看
链接:http://poj.org/problem?id=1986
算法概述:所谓离线,就是把所有要求公共祖先的结点对用邻接表存起来,输入完毕后一起计算。
算法实现不困难,就是并查集和DFS。
从根开始遍历,遍历到新的结点时将该点记录为根(H[u]=u),建立以这个点为根的集合。对这个集合的每个子树进行搜索,即将子树内部的存在的所有LCA询问解决。当搜索到LCA的一个点,另外一个点被询问过了,最近公共祖先就是另外一个点此时的根。如果有子树中LCA没有解决,则其LCA询问不在这个根的子树内,将该子树所有点的根记录为u。由于是递归实现,则保证最先找到的最近的祖先。看代码显而易见。
题意:给N个农场,给出M对农场之间的距离。计算K对农场的距离。
思路:是一道标准的模板题。数据量到不能用最短路算,所以用LCA。记录从根到每个点之间的深度,答案就是ans[i]=d[query[i].v]+d[u]-2*d[findset(query[i].v)]。
代码:
算法概述:所谓离线,就是把所有要求公共祖先的结点对用邻接表存起来,输入完毕后一起计算。
算法实现不困难,就是并查集和DFS。
从根开始遍历,遍历到新的结点时将该点记录为根(H[u]=u),建立以这个点为根的集合。对这个集合的每个子树进行搜索,即将子树内部的存在的所有LCA询问解决。当搜索到LCA的一个点,另外一个点被询问过了,最近公共祖先就是另外一个点此时的根。如果有子树中LCA没有解决,则其LCA询问不在这个根的子树内,将该子树所有点的根记录为u。由于是递归实现,则保证最先找到的最近的祖先。看代码显而易见。
题意:给N个农场,给出M对农场之间的距离。计算K对农场的距离。
思路:是一道标准的模板题。数据量到不能用最短路算,所以用LCA。记录从根到每个点之间的深度,答案就是ans[i]=d[query[i].v]+d[u]-2*d[findset(query[i].v)]。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<map> #include<queue> #include<stack> #include<vector> #include<ctype.h> #include<algorithm> #include<string> #define PI acos(-1.0) #define maxn 100005 #define INF 1<<25 #define MAX 0x7fffffff typedef long long ll; using namespace std; struct Edge { int v,w; int next; } edge[maxn],query[maxn]; int ans[maxn],point[maxn],head[maxn],d[maxn],aa[maxn],H[maxn],vv[maxn],tot,tt;; int e_top,q_top; int init() { e_top=q_top=0; memset(vv,0,sizeof(vv)); memset(head,-1,sizeof(head)); memset(aa,0,sizeof(aa)); memset(point,-1,sizeof(point)); memset(ans,0,sizeof(ans)); memset(d,0,sizeof(d)); memset(H,0,sizeof(H)); } int add_edge(int u,int v,int w) { edge[e_top].v=v; edge[e_top].w=w; edge[e_top].next=head[u]; head[u]=e_top++; edge[e_top].v=u; edge[e_top].w=w; edge[e_top].next=head[v]; head[v]=e_top++; } int add_query(int u,int v) { query[q_top].v=v; query[q_top].next=point[u]; point[u]=q_top++; query[q_top].v=u; query[q_top].next=point[v]; point[v]=q_top++; } int findset(int x) { return x==H[x]?x:H[x]=findset(H[x]); } int dfs(int u,int w) { d[u]=w,H[u]=u; vv[u]=1; for(int i=head[u]; i!=-1; i=edge[i].next) { if(!vv[edge[i].v]) { dfs(edge[i].v,w+edge[i].w); H[edge[i].v]=u; } } for(int i=point[u];i!=-1;i=query[i].next) { if(vv[query[i].v]) ans[i]=d[query[i].v]+d[u]-2*d[findset(query[i].v)]; } } int main() { scanf("%d%d",&tot,&tt); init(); for(int i=0;i<tt;i++) { int x,y,z; char ss[2]; scanf("%d%d%d%s",&x,&y,&z,ss); add_edge(x,y,z); } scanf("%d",&tt); for(int i=0;i<tt;i++) { int x,y; scanf("%d%d",&x,&y); add_query(x,y); } dfs(1,0); for(int i=0;i<tt*2;i+=2) { if(ans[i]==0) printf("%d\n",ans[i+1]); else printf("%d\n",ans[i]); } }
相关文章推荐
- (算法)Tarjan离线算法解决LCA问题 (附POJ 1470 Closest Common Ancestors 代码)
- POJ1986 DistanceQueries 最近公共祖先LCA 离线算法Tarjan
- POJ 1470 LCA tarjan 离线算法
- POJ 1330 Nearest Common Ancestors 【LCA·Tarjan离线算法】
- LCA三种算法学习(离线算法tarjan+在线算法转rmq+在线倍增)例题poj1330、1470;hdu4547、2874
- POJ 1984 Distance Queries LCA
- poj 3529 Network 双连通分连 动态求桥的数目 + tarjan离线算法求LCA
- POJ 1986 Distance Queries LCA树上两点的距离
- POJ1986 DistanceQueries 最近公共祖先LCA 离线算法Tarjan
- POJ 1986 Distance Queries LCA
- POJ 1986 Distance Queries(LCA Tarjan离线算法)
- (算法)Tarjan离线算法解决LCA问题 (附POJ 1470 Closest Common Ancestors 代码)
- POJ 1330 Nearest Common ancesters(LCA,Tarjan离线算法)
- poj 1330 Nearest Common Ancestors (LCA) tarjan离线算法
- Distance Queries POJ - 1986 (LCA在线方法求解 公共祖先(带权值))
- Tarjan离线算法求LCA小结
- POJ 1330 ---(线段树在线LCA 与 tarjan离线LCAs)
- POJ 1330 最近公共祖先LCA_Tarjan 【水】
- LCA的离线算法 tarjan
- 【tarjan双连通+LCA求割边数】POJ 3694