您的位置:首页 > 其它

【Lca 离线Tarjan算法】hdu 2586 How far away ?

2017-07-08 22:17 447 查看
LCA 离线Tarjan算法
题意: 对于一个图,n(<=40000)个点,给出n-1条边(u,v,w,), m(<=200)个询问给出两点,问其最短距离。

Tarjan 离线求LCA:
离线算法(必然先存所有询问);
dfs:
1. 遍历到当前点,创造一个当前点的集合
2. 对于遍历完的子树,将其根节点的集合加入其父节点所在的集合。
3. 对于询问的两点,遍历到一点,如果另一点已经被遍历,那么另一点已经加入集合的最高那一点即为最近公共祖先。
4. 因为另一点可能在此点的子树上,所以询问的答案应该在遍历完其子树后执行。

注意: 问题的记录最好用前向星写吧。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
//#pragma comment(linker, "/STACK:102400000,102400000")

const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF=0x3f3f3f3f;
const LL mod = 1e9+7;
const int N = 100000+10;
const int M = 2500000;

struct Node
{
int from;
int to;
int val;
int next;
};
int dir
,fa
,vis
;
vector<Node> ma
;     //vector 记录图
Node query[N*2];
int head
;
int ans
;
void addquery(int u,int v,int &top)
{
query[++top].from = u; query[top].to = v; query[top].next = head[u];
head[u] = top;
query[++top].from = v; query[top].to = u; query[top].next = head[v];
head[v] = top;
}
int Find(int n)
{
if(fa
!= n){
fa
= Find(fa
);
}
return fa
;
}
void dfs(int n,int dist)  //dfs处理需要数组
{
fa
= n;
vis
=true;
dir
=dist;
for(int i = 0; i < ma
.size(); i++){
Node temp = ma
[i];
if(!vis[temp.to]){
dfs(temp.to,dist+temp.val);
fa[temp.to] = n;
}
}
for(int i = head
; i != -1; i=query[i].next){
int v = query[i].to;
if(vis[v]){
int pa = Find(v);
//query[i].val = dir
+dir[v]-2*dir[pa];
ans[(i-1)/2] = dir
+dir[v]-2*dir[pa];
}
}
}

int main()
{
int T;
scanf("%d",&T);
while(T--){
memset(vis,0,sizeof(vis));
memset(head,-1,sizeof(head));
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++){
ma[i].clear();
}
for(int i = 1; i < n; i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
Node temp;
temp.to = v; temp.val = w;
ma[u].push_back(temp);
temp.to = u; temp.val = w;
ma[v].push_back(temp);
}
int top = 0;
for(int i = 0; i < m; i++){
int u,v;
scanf("%d%d",&u,&v);
addquery(u,v,top);
}
dfs(1,0);
for(int i = 0; i < m; i++){
printf("%d\n",ans[i]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: