hdu2586 树上两点之间的距离 tarjan
来源:互联网 发布:java语言程序设计 pdf 编辑:程序博客网 时间:2024/05/31 15:19
How far away ?
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6650 Accepted Submission(s): 2475
Problem Description
There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.
Input
First line is a single integer T(T<=10), indicating the number of test cases.
For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.
For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.
Output
For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.
Sample Input
23 21 2 103 1 151 22 32 21 2 1001 22 1
Sample Output
1025100100
那么我们是否可以固定一个树根,然后计算每个点到树根的距离dist,假设a,b的LCA是c,那么a到b这条路径我们可以拆成a->c,c->b,这个信息我们显然无法得到,那么我们加上两端c->root,root->c,合并后就是a->root,root->b,也就是dist[a]+dist[b],因为我们多加了两段2*dist[c],因此最后就是dist[a]+dist[b]-2*dist[c]。
这里可用在线RMQ算法来处理欧拉序列或者使用离线tarjan算法。
在线RMQ算法较好理解,而tarjan算法有点难理解。
其实tarjan思想的本质就是递归处理,假设我们当前在处理u的点,我们须先处理u的所有子树(这里是递归),然后访问完u的子树,表示u已访问完毕,我们将vis[u]置1,然后立刻处理与u向关联的询问,假设询问(u,v),那么我们考察一下v是否被访问,假设vis[v]=0,那么我们不处理,因为下次当我们访问到v时再来处理(v,u){此时u已访问},为了保证算法正确性,我们对每个询问标记两次,(u,v)和(v,u),即保证处理到一次。而对于vis[v]=1的情况,我们要处理(u,v)的LCA,那么LCA是什么呢?画张图就知道了,一定是访问完v往上走之后下到u,因此我们需要并查集记录一下,对u每访问完一个子树,将子树与u合并,然后让该集合指向u,也就是上走到u,可以画张图,应该就能理解。
代码:
#include<iostream>#include<cstdio>#include<cstring>#define Maxn 40010#define Maxm 210using namespace std;struct edge{ int fr,to,w,lca,next;}p[Maxn<<1],ask[Maxm<<1];int head[Maxn],ah[Maxn];int tot,tot1;void addedge(int a,int b,int c){ p[tot].to=b; p[tot].w=c; p[tot].next=head[a]; head[a]=tot++;}void addedge1(int a,int b){ ask[tot1].fr=a; ask[tot1].to=b; ask[tot1].next=ah[a]; ah[a]=tot1++;}int fa[Maxn];int findset(int x){ return fa[x]==x?x:(fa[x]=findset(fa[x]));}void unionset(int a,int b){ fa[findset(a)]=findset(b);}int vis[Maxn];int anc[Maxn];int dist[Maxn];void LCA(int u,int fa){ for(int i=head[u];i!=-1;i=p[i].next){ int v=p[i].to; if(fa!=v){ dist[v]=dist[u]+p[i].w; LCA(v,u); unionset(u,v); //将子树合并到父亲 anc[findset(u)]=u; //维护新集合指向父亲 } } vis[u]=1; //设置已访问 for(int i=ah[u];i!=-1;i=ask[i].next){ //处理与u关联的边 int v=ask[i].to; if(vis[v]) //若v已访问,则说明u,v的lca是v所在集合的指向 ask[i].lca=ask[i^1].lca=anc[findset(v)]; }}void init(int n){ tot=tot1=0; memset(head,-1,sizeof head); memset(ah,-1,sizeof ah); memset(vis,0,sizeof vis); for(int i=1;i<=n;i++) fa[i]=i;}int main(){ int t,n,m,a,b,c; cin>>t; while(t--){ cin>>n>>m; init(n); for(int i=1;i<n;i++){ scanf("%d%d%d",&a,&b,&c); addedge(a,b,c); addedge(b,a,c); } for(int i=1;i<=m;i++){ scanf("%d%d",&a,&b); addedge1(a,b); addedge1(b,a); } dist[1]=0; LCA(1,-1); for(int i=0;i<tot1;i+=2) printf("%d\n",dist[ask[i].fr]+dist[ask[i].to]-2*dist[ask[i].lca]); } return 0;}
0 0
- hdu2586 树上两点之间的距离 tarjan
- 两点之间的距离
- 两点之间的距离
- 两点之间的距离
- hdu 2376(求树上任意两点之间距离之和的平均值)
- poj 2763 Housewife Wind 动态求树上两点之间距离
- 求两点之间的距离
- 求两点之间的距离
- 求两点之间的距离
- 求两点之间的距离
- 求两点之间的距离
- 计算两点之间的距离
- 计算两点之间的距离
- 获取两点之间的距离
- 计算两点之间的距离
- 4.22两点之间的距离
- 计算两点之间的距离
- 求两点之间的距离
- 从游戏设计到星际探险,微软HoloLens全息技术将改变什么?
- Python爬虫爬学校民主湖(4)------------模拟登录
- 第一个Cocos2d-JS游戏
- HashMap,LinkedHashMap,TreeMap的区别
- hiho一下第二周:Trie树
- hdu2586 树上两点之间的距离 tarjan
- 农夫卖鸡问题->数学趣题
- poj完整分类
- Android Progress进度条代码,进度条刷新问题探讨
- hdu1532(最大流)
- 基于SmartAction工具的自动化,研究与探索
- 手机短信验证码的实现
- 半秒内筛一亿以内的所有素数
- 4个月,工厂女工转型魔都白领