HDU 2586

来源:互联网 发布:淘宝开店话费充值 编辑:程序博客网 时间:2024/04/20 11:39

离线Tarjan算法。LCA问题。

题目链接

【解题思路】

先用DFS求出所有点到根节点的距离,记为dis[x]。

然后,用Tarjan算法求出LCA。

Tarjan算法

#include <cstdio>#include <cstring>#include <vector>using namespace std;typedef long long LL;#define root 1#define Maxn 50005int n,Q;bool vis[Maxn];LL dis[Maxn];LL ans[Maxn];int fa[Maxn];struct Node{int to , lca , val , id; };vector <Node> adj[Maxn];vector <Node> q[Maxn];inline void Add_Edge(int fr,int to,int v){adj[fr].push_back( (Node){to,0,v,0} );adj[to].push_back( (Node){fr,0,v,0} );}inline void Add_Q_Edge(int fr,int to,int id){q[fr].push_back( (Node){to,0,0,id});q[to].push_back( (Node){fr,0,0,id});}void dfs(int u,int f,LL val){dis[u] = val;int S = adj[u] . size();for(int i=S-1;i>=0;i--){Node v = adj[u][i];if(v.to == f) continue;dfs(v.to,u,val + v.val); }}int find(int x){if(fa[x] != x) fa[x] = find(fa[x]);return fa[x];}void LCA(int u){vis[u] = true;fa[u] = u;int S = adj[u] . size();for(int i=S-1;i>=0;i--){Node &v = adj[u][i];if(!vis[v.to]){LCA(v.to); fa[v.to] = u;}}S = q[u] . size();for(int i=S-1;i>=0;i--){Node &v = q[u][i];if(!vis[v.to]) continue;v.lca = find(v.to);ans[v.id] = dis[u] + dis[v.to] - 2 * dis[v.lca];}}void print(){for(int i=1;i<=Q;i++) printf("%d\n",ans[i]);}int main(){int T;int x,y,z;scanf("%d",&T);while(T--){memset(ans,0,sizeof(ans));memset(vis,0,sizeof(vis));memset(dis,0,sizeof(dis));memset(adj,0,sizeof(adj));memset(q,0,sizeof(q));scanf("%d%d",&n,&Q);for(int i=1;i<=n;i++) fa[i] = i;for(int i=1;i<n;i++){scanf("%d%d%d",&x,&y,&z);Add_Edge(x,y,z);}for(int i=1;i<=Q;i++){scanf("%d%d",&x,&y);Add_Q_Edge(x,y,i);}dfs(root,0,0);LCA(root);print();}return 0;}

但是,还有一个问题,这样有可能会暴栈,不过,加上模拟栈就可以了。

1 0
原创粉丝点击