【POJ 1986】 Distance Queries 解题报告

刚刚学了LCA的ST算法,这是一道很好的模板题,题目输入最后的英文字母请无视,没有卵用。

代码如下

/*My convictions will not falter.--Poppy*/
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
const int N=100005;
using namespace std;
int head[N],first[N],dis[N],ver[N],r[N],ss[N][35];
int num;
bool pd[N];
struct Edge
{
    int from,to,next,w;
}s[2*N];
int log2(int x)
{
    int ans=0,tmp=1;
    while(tmp*2<=x)
      tmp*=2,ans++;
    return ans;
}
void add(int from,int to,int w)
{
    s[++num].next=head[from];
    s[num].from=from,s[num].to=to,s[num].w=w;
    head[from]=num;
    return ;
}
void read(int &x)
{
    x=0;char c=getchar();
    while(c<48||c>57) c=getchar();
    while(c>=48&&c<=57) x=x*10+c-48,c=getchar();
    return ;
}
void read(char &c)
{
    c=getchar();
    while(c<'A'||c>'Z') c=getchar();
    return ;
}
void dfs(int u,int dep)
{
    pd[u]=1;
    ver[++num]=u;//第num个节点的编号 
    first[u]=num;//第一次访问u节点时间  
    r[num]=dep;//深度 
    for(int i=head[u];i;i=s[i].next)
    {
        int v=s[i].to;
        if(!pd[v])
        {
            dis[v]=dis[u]+s[i].w;
            dfs(v,dep+1);
            ver[++num]=u;r[num]=dep;
        }
    }
    return ;
}
void ST(int t)
{
    int max_line=log2(t);
    for(int i=1;i<=t;i++) ss[i][0]=i;
    for(int j=1;j<=max_line;j++)
      for(int i=1;i+(1<<j)-1<=t;i++)
            ss[i][j]=r[ss[i][j-1]]<r[ss[i+(1<<j-1)][j-1]]? ss[i][j-1]:ss[i+(1<<j-1)][j-1];
}
void swap(int &x,int &y)
{
    int z;
    z=x,x=y,y=z;
}
int LCA(int x,int y)
{
    x=first[x];y=first[y]; 
    if(x>y) swap(x,y);
    int max1=log2(y-x+1);
    return ver[r[ss[x][max1]]<r[ss[y-(1<<max1)+1][max1]]? ss[x][max1]:ss[y-(1<<max1)+1][max1]];
}
int main()
{
    int n,m,a,b,d;
    char ccc;
    read(n);read(m);
    for(int i=1;i<=m;i++)
    {
        read(a);read(b);read(d);read(ccc);
        add(a,b,d);
        add(b,a,d);
    }
    num=0;
    dfs(1,1);
    ST(num);
    read(m);
    for(int i=1;i<=m;i++)
    {
        read(a);read(b);
        int ff=LCA(a,b);
        printf("%d\n",dis[a]+dis[b]-2*dis[ff]);
    }
    return 0;
}

注意:
①r数组和ver数组是记录的第num个访问到的点的值,而first是记录u节点的信息,不要搞混
②<<优先级最低(甚至比’+’,’-‘还低)一定要用括号括起来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值