POJ--1986--Distance Queries--LCA-RMQ

来源:互联网 发布:微信盗取软件 编辑:程序博客网 时间:2024/05/04 19:34

题目大意:求一棵树任意两点的距离

解题报告,设一个数组 dis[i]表示i节点到跟节点的距离,则任意两点的最短距离:dis[i,j]=dis[i]+dis[j]-2*dis[LCA(i,j)]

这个公式还是比较直接的吧

这样就转化成了一个LCA问题。召唤模板

就不吐槽WA到死的代码,换个节点存储方式就过了,简化的数据存储方式可以降低编程复杂度。

PS:此题中的东西南北的方向是不需要的

个人感觉就是1985加上个RMQ模板

#include<iostream>#include<cstring>#include<cstdio>#include<vector>#define maxn 51000using namespace std;vector<int> g[maxn];    //树的存储结构vector<int> elen[maxn]; //存储边权int r[maxn];        //RMQ问题中标记节点第一次在e数组中出现的位置int e[maxn*2];      //RMQ问题中深搜记录边访问的节点 int l[maxn*2];      //RMQ问题中记录节点的访问深度int dp[maxn*2][20]; int res[maxn*2][20];int ei,n,m,root,x,y;bool vis[maxn];int dis[maxn];      //dis[i]表示i节点到根节点的距离,此题中根节点是1void init(){    int x,y,l;    char dir[10];    scanf("%d%d",&n,&m);    memset(dis,0,sizeof(dis));    for(int i=1;i<=m;i++)    {        scanf("%d%d%d%s",&x,&y,&l,dir);        g[x].push_back(y);        elen[x].push_back(l);        g[y].push_back(x);        elen[y].push_back(l);    }}void _dfs(int u) //深搜确定节点之间的继承关系以及以u为根节点的子树的最远叶子距离{    vis[u]=1;    int v,vlen=g[u].size();    for(int i=0;i<vlen;i++)    {        v=g[u][i];        if(!vis[v])        {                dis[v]=dis[u]+elen[u][i];                _dfs(v);        }    }}void rdfs(int u,int dep){    vis[u]=1;    e[ei]=u;    l[ei]=dep;    r[u]=ei;    ei++;    int v,vlen=g[u].size();    for(int i=0; i<vlen; i++)    {        v=g[u][i];        if(!vis[v])        {            rdfs(v,dep+1);            e[ei]=u;            l[ei]=dep;            ei++;        }    }}void RMQ_init(){    for(int i=0; i<ei; i++)    {        dp[i][0]=l[i];        res[i][0]=e[i];    }    for(int j=1; (1<<j)-1<ei; j++)    {        for(int i=0; i+(1<<j)<ei; i++)        {            x=dp[i][j-1];            y=dp[i+(1<<(j-1))][j-1];            if(x<y)            {                dp[i][j]=x;                res[i][j]=res[i][j-1];            }            else            {                dp[i][j]=y;                res[i][j]=res[i+(1<<(j-1))][j-1];            }        }    }}int RMQ(int lx,int ly){    int len=0;    while(lx+(1<<(len+1))-1<=ly)len++;    x=dp[lx][len];    y=dp[ly-(1<<len)+1][len];    if(x<y)return res[lx][len];    else return res[ly-(1<<len)+1][len];}void solve(){    memset(vis,0,sizeof(vis));    _dfs(1);    memset(vis,0,sizeof(vis));    ei=0;    rdfs(1,1);    RMQ_init();    int a,b;    int ic,ans,x,px;    scanf("%d",&ic);    for(int i=0;i<ic;i++)    {        scanf("%d%d",&a,&b);        if(r[a]>r[b])swap(a,b);        int tar=RMQ(r[a],r[b]);        ans=dis[a]+dis[b]-2*dis[tar];        printf("%d\n",ans);    }}int main(){    freopen("1986.txt","r",stdin);    init();    solve();    return 0;}



原创粉丝点击