1. 程式人生 > >HD2586 LCA水題

HD2586 LCA水題

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水題