Day1 T2 树的链接

树的链接

D国有n个城市,有若干条道路,每条道路能连接两个城市,并且有一定的长度。

初始时,并没有任何道路存在。接下来,有q个操作需要你依次完成:

x y 表示:询问城市x与y之间的最短路径长度;如果不存在任何路径,则你应当回答−1。
x y w 表示:在城市x与y之间修建了一条长度为 w 的道路。保证在此之前在城市 x 与 y 之间不存在任何路径(即:假如在此之前给出一个x y的操作,保证其答案应当为−1)。
输入格式

输入的第一行包含两个正整数n, q。

接下来q行,每行输入两个或者三个正整数,形如x y或x y w,表示一个操作。

每行中,相邻的两个数之间用一个空格隔开。

输出格式

对于每个形如x y的操作,你需要输出一行,包含一个整数,为你对于这次询问的答案。

数据范围

对于测试点1,21,2,保证$ n, q \leq 200$

对于测试点1,2,3,41,2,3,4,保证$ n, q \leq 2000$

对于测试点1,2,3,4,5,61,2,3,4,5,6,保证$ n, q \leq 100,000$

编号为奇数的测试点满足:所有形如 x y w 的询问都出现在所有形如 x y 的询问之后。

对于所有数据,保证$ 1 \leq n, q \leq 500,000$所有的 w 均为不超过1000的正整数。

Lca

数据结构

link(u,v)
query(u,v)

将询问绕(到、跳)着做$\rightarrow$多做几次$\rightarrow$离线

读入,不能用$\color{red}{"cin"}$,因为cin只读第一个可见字符

$\color{blue}{用scanf}$

cin>>n>>q;
for(int i=1;i<=q;i++)
{
    cin>>qx[i]>>qy[i];
    char c=getchar();
    if(c==' ')
    {
        cin>>qw[i];
        add_edge(qx[i],qy[i],qw[i]);
        add_edge(qy[i],qx[i],qw[i]);
    }
    else
        qw[i]=-1;
}
for(u=1;u<=n;u++)
    if(fa[u][0]==0)
        dfs(u);
for(k=1;k<=20;k++)
    for(int u=1;u<=n;u++)
    {
        int v=fa[u][k-1];
        fa[u][k]=fa[v][k-1];
        g[u][k]=g[v][k-1]+g[u][k-1];
    }
for(i=1;i<=q;i++)
    {
        int u=qx[i];
        int v=qy[i];
        if(qw[i]==-1)
        {
            if(find(u)==find[v])
                cout<<path(u,v)<<endl;
            else
                cout<<-1<<endl;
        }
        else
            p[find[u]]=find[v];
    }
void dfs(int u)
{
    d[u]=d[fa[u][0]]+1;
    for(int i=head[u];i;i=e[i].next)
    {
        v=e[i].to;
        if(v!=fa[u][0])
        {
            g[v][0]=e[i].val;
            fa[v][0]=u;
            dfs(v);
        }
    }
}
int path(int u,int v)
{
    int sum=0;
    if(d[u]<d[v])
        return path(v,u);
    for(int k=20;k>=0;k--)
    {
        int uu=fa[u][k];
        if(d[uu]>=d[v])
        {
            sum+=g[u][k];
            u=uu;
        }
    }
    if(u==v)
        return sum;
    for(int k=20;k>=0;k--)
    {
        int uu=fa[u][k];
        int vv=fa[u][k];
        if(vv!=uu)
        {
            sum+=g[u][k];
            sum+=g[v][k];
            u=uu;
            v=vv;
        }
    }
    return sum+g[u][0]+g[v][0];
}

猜你喜欢

转载自www.cnblogs.com/AntonioYAO/p/11666174.html