HDU 2586 How far away ? 离线LCA

来源:互联网 发布:淘宝哪家情侣装好看 编辑:程序博客网 时间:2024/05/18 20:09

题意:有n个点,m条无向边,有q次询问,问点a到点b的距离。


想法:点的个数有4000个,询问 200个,用floyd超时, spfa暴力没试过,这里用离线LCA算法。
离线LCA就是,先保存查询的边(双向),然后dfs每一个点,回溯的时候合并点,然后在询问里面找当前点u的下一个点v有没有被访问过,如果被访问过,就记录记过dis[u]+dis[v]-2*dis[zuxian[v]]


#pragma comment(linker,"/STACK:1000000000,1000000000")#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int N=400000+5;int father[N];int head2[N],cnt2,head[N],cnt;int ans[N];int anc[N],vis[N],dis[N];struct node{    int id;    int to,next;    int len;};struct node G[N],QG[N];void Init(){    cnt=0;cnt2=0;    memset(vis,0,sizeof(vis));    memset(dis,0,sizeof(dis));    memset(head2,-1,sizeof(head2));    memset(head,-1,sizeof(head));}void add1(int a,int b,int id){    QG[cnt].to=b;    QG[cnt].id=id;    QG[cnt].next=head[a];    head[a]=cnt++;}void add2(int a,int b,int c){    G[cnt2].to=b;    G[cnt2].len=c;    G[cnt2].next=head2[a];    head2[a]=cnt2++;}int find_set(int x){    if(x!=father[x])    {        father[x]=find_set(father[x]);    }    return father[x];}void union_set(int x,int y){    x=find_set(x);    y=find_set(y);    if(x==y) return;    father[y]=x;} void lca_tarjan(int u,int len){    vis[u]=1;    dis[u]=len;    for(int i=head2[u];i+1;i=G[i].next)    {        int v=G[i].to;        int w=G[i].len;        if(vis[v]) continue;        lca_tarjan(v,len+w);        union_set(u,v);    }    for(int j=head[u];j+1;j=QG[j].next)    {        int v=QG[j].to;        int id=QG[j].id;        if(!vis[v]) continue;        ans[id]=dis[u]+dis[v]-2*dis[find_set(v)];    }}int main(){    int m,n;    int t;    scanf("%d",&t);    while(t--)    {        Init();        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++)        {            father[i]=i;        }        for(int i=1;i<=n-1;i++)        {            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            add2(a,b,c);            add2(b,a,c);        }        for(int i=1;i<=m;i++)        {            int a,b;            scanf("%d%d",&a,&b);            add1(a,b,i);            add1(b,a,i);        }        memset(ans,0,sizeof(ans));        lca_tarjan(1,0);        for(int i=1;i<=m;i++)        {            printf("%d\n",ans[i]);        }    }    return 0;}

0 0
原创粉丝点击