HD2586 LCA水題
阿新 • • 發佈:2017-10-07
greatest 既然 next 強連通 www. and htm 查詢 false
強連通 1269 迷宮城堡 2767 Proving Equivalences 3836 Equivalent Sets 1827 Summer Holiday 3072 Intelligence System 3861 The King’s Problem 3639 Hawk-and-Chicken 3594 Cactus 仙人掌圖 4685 [雙連通]: 2242 考研路茫茫——空調教室 雙聯通縮點+樹形DP 2460 Network 邊雙連通 3849 By Recognizing These Guys, We Find Social Networks Useful 雙連通求橋 3896 Greatest TC 雙連通4005 The war 邊雙連通 3394 Railway 雙連通求塊 [LCA]: 2586 How far away ? 2874 Connections between cities 3078 Network 3830 Checkers 4338 Simple Path
參考Vendetta:
需要補充的是vis可以在訪問到節點時就標記,也可以在訪問完其子孫後再標記,區別在於前者可以查詢a和b的關系以及b和a的關系,而後者只能查詢b和a的關系(假設先訪問a),但既然是無向圖,答案是一樣的,目測放前面可能更強大。
#include<cstdio>
#include <cstring>
#include<cstring>
#include<iostream>
int const MAX = 40005;
struct Edge
{
int id, val;
int next;
}e[2 * MAX];
int n, m, cnt;
int x[MAX], y[MAX], z[MAX];
int fa[MAX], dist[MAX], pre[MAX];
bool vis[MAX];
void _add(int u, int v, int w)
{
e[cnt].id = u;
e[cnt].val = w;
e[cnt].next = pre[v];
pre[v] = cnt++;
}
int Find(int x)
{
return x == fa[x] ? x : fa[x] = Find(fa[x]);
}
void tarjan(int k)
{
vis[k]=true;
fa[k]=k;
for(int i=pre[k];i;i=e[i].next){
if(!vis[e[i].id]){
dist[e[i].id]=dist[k]+e[i].val;
tarjan(e[i].id);
fa[e[i].id] = k;
}
}
//vis[k]=true;
for(int i=1;i<=m;i++){
if(x[i]==k&&vis[y[i]])
z[i]=Find(y[i]);
}
}
int main()
{
int T,u,v,w;
scanf("%d",&T);
while(T--){
scanf("%d %d", &n, &m);
cnt=0;
memset(pre,0,sizeof(pre));
for(int i=1;i<n;i++){
scanf("%d %d %d",&u,&v,&w);
_add(u,v,w);
_add(v,u,w);
}
for(int i=1;i<=n;i++)
x[i]=y[i]=z[i]=0;
for(int i=1;i<=m;i++)
scanf("%d %d",&x[i],&y[i]);
memset(vis, false, sizeof(vis));
dist[1] = 0;
tarjan(1);
for(int i = 1; i <= m; i++)
printf("%d\n",dist[x[i]] + dist[y[i]] - 2 * dist[z[i]]);
}
}
HD2586 LCA水題