リンク1日目T2ツリー

リンクツリー

状態D N都市、道路の数は、各道路は、二つの都市を接続し、一定の長さを有することができます。

最初に、どの道がありません。次に、操作はご注文を完了する必要がありqがあります。

xyが表し:XとYの都市間の尋問路長を、何のルートが存在しない場合、あなたは答える必要-1。
xywを表す:道路の長さWの都市建設の間のxとyを。(すなわち:XY前の動作を説明すれば、答えは確実にすべきである-1)任意パスが存在しないことを確実にするために都市およびX yの間先行。
入力形式

入力の最初の行は2つの正の整数N、Qを含んでいます。

次のQ二つまたは三つの入力の正の整数の列、又はxyw XYような形状、動作を表します。

各行において、スペースで区切られた2つの隣接する数字間。

出力フォーマット

フォームXYの各動作のためには、このクエリへのあなたの答えのために、出力に整数を含む1行を必要としています。

データ範囲

テストポイント1,21,2のために$ nは、Q \当量200 $を確保

テストポイント1,2,3,41,2,3,4のために確保するために$ N、Qの\の当量2000 $その

テストポイント1,2,3,4,5,61,2,3,4,5,6のためにその$ N、Qの\の当量$ 100,000を確保するために、

満足奇数テストポイント:すべてがxyw質問状に形成されているが、XYのような形をすべての質問の後に起こります。

すべてのデータの場合、確実にするためにその$ 1 \当量のn、q個の\当量50万$ wは、すべての正の整数1,000以上ではありません。

LCA

データの構造

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

私たちは、$ \のRIGHTARROWが数回以上$ $ \ RIGHTARROW $オフライン作る(ジャンプする)の周りに聞いてきます

読んで、することができません$ \色{赤}、{「CIN」} $、最初の読み取り専用見える文字CINとして

$の\カラー{青} {用の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