poj 1986 Distance Queries 离线LCA

来源:互联网 发布:中断windows更新 编辑:程序博客网 时间:2024/06/17 11:28

题目链接

http://poj.org/problem?id=1986

题意

给定一个树,和q个询问,求出两点间最短距离

思路

d[u]代表u到根结点的距离,所以u与v之间的距离为d[u]+d[v]-2*d[lca(u,v)]

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<string>#include<queue>#include<stack>#include<set>#include<map>#define ll long longusing namespace std;const int INF = ( 2e9 ) + 2;const ll maxn = 1e6+10;struct edge{    int v,w,next,id;}e1[2*maxn],e2[maxn];int head1[maxn],head2[maxn];int tot1,tot2;int In[maxn],f[maxn],ans[maxn],d[maxn];bool vis[maxn];void add1(int u,int v,int w){    e1[tot1].v=v;    e1[tot1].w=w;    e1[tot1].next=head1[u];    head1[u]=tot1++;}void add2(int u,int v,int id){    e2[tot2].v=v;    e2[tot2].id=id;    e2[tot2].next=head2[u];    head2[u]=tot2++;}void init(){    memset(head2,-1,sizeof(head2));    memset(head1,-1,sizeof(head1));    memset(In,-1,sizeof(In));    memset(vis,0,sizeof(vis));    tot1=tot2=0;}int Find(int x){    return f[x]==x?x:Find(f[x]);}void dfs(int u){    vis[u]=1;    f[u]=u;    for(int i=head2[u];i!=-1;i=e2[i].next)    {        int v=e2[i].v,id=e2[i].id;        if(vis[v])        ans[id]=d[u]+d[v]-2*d[Find(v)];    }    for(int i=head1[u];i!=-1;i=e1[i].next)    {        int v=e1[i].v,w=e1[i].w;        if(!vis[v])        {            d[v]=d[u]+w;            dfs(v);            f[v]=u;        }    }}int main(){    int n,m;    while(~scanf("%d%d",&n,&m))    {        int u,v,w;        char s[2];        init();        for(int i=0;i<m;i++)        {            scanf("%d%d%d%s",&u,&v,&w,s);            add1(u,v,w);            add1(v,u,w);            In[v]++;        }        int k;        scanf("%d",&k);        for(int id=1;id<=k;id++)        {            scanf("%d%d",&u,&v);            add2(u,v,id);            add2(v,u,id);        }        int root;        for(int i=1;i<=n;i++)        if(In[i]==0)root=i;        dfs(root);        for(int i=1;i<=k;i++)        printf("%d\n",ans[i]);    }}
原创粉丝点击