HDU6115(LCA)

来源:互联网 发布:数据报网络 编辑:程序博客网 时间:2024/06/06 09:39

题解:对于每次询问,把两个子公司的所有点对都枚举出来,用LCA求点对的最近距离,然后求最小值。

#include <bits/stdc++.h>using namespace std;#define N 100010struct Edge{    int x,w;    Edge(int x,int w):x(x),w(w){}};vector<Edge> g[N];vector<int> vec[N];int fa[N][20],dep[N],h[N];int n,m;void dfs(int x,int p){    h[x]=h[p]+1;    fa[x][0]=p;    for(int i=1;i<20;++i)        fa[x][i]=fa[fa[x][i-1]][i-1];    int y;    for(int i=0;i<g[x].size();++i)    {        y=g[x][i].x;        if(y==p) continue;        dep[y]=dep[x]+g[x][i].w;        dfs(y,x);    }}int lca(int x,int y){    if(h[x]<h[y]) swap(x,y);    int d=h[x]-h[y];    for(int i=0;i<20;++i)        if((d>>i)&1) x=fa[x][i];    if(x==y) return x;    for(int i=19;i>=0;--i)        if(fa[x][i]!=fa[y][i])        {            x=fa[x][i];y=fa[y][i];        }    return fa[x][0];}int main(){    int ca;    scanf("%d",&ca);    while(ca--)    {        scanf("%d%d",&n,&m);        for(int i=1;i<=n;++i) g[i].clear();        for(int i=1;i<=m;++i) vec[i].clear();        int x,y,w;        for(int i=1;i<n;++i)        {            scanf("%d%d%d",&x,&y,&w);            g[x].push_back(Edge(y,w));            g[y].push_back(Edge(x,w));        }        for(int i=1;i<=m;++i)        {            scanf("%d",&w);            for(int j=1;j<=w;++j)            {                scanf("%d",&x);                vec[i].push_back(x);            }        }        dfs(1,0);        int Q,u,v,ans;        scanf("%d",&Q);        while(Q--)        {            scanf("%d%d",&u,&v);            ans=1e9;            for(auto x:vec[u])                for(auto y:vec[v])                {                    ans=min(ans,dep[x]+dep[y]-2*dep[lca(x,y)]);                }            printf("%d\n",ans);        }    }    return 0;}
原创粉丝点击