【gdgzezoi】問題C:ツリー

説明

ネットオフルーム!XJ簡単てこZWLが中に入った引っ張って、部屋の中央のロックを開けます。彼らは、中央のホストが爆発していることが分かりました。

中心の破片のn個に爆発分割後コンソールが、デブリは依然としてツリーの構造を形成するために互いに接続されています。各断片は、0または1の状態の値を有します。ビット法則を見つけるZWL、我々はすべての値と同じ時間の状態の断片のみが、ホストが修理できるようになりますことを見出しました。

前記デブリは、XJ Xをタッチすることが見出されたX-Vへの経路上で同じ状態のすべてのフラグメントおよびx値の状態値を満たすそれらのフラグメントは、Vネゲート状態値(0、1となる0になる)です!

今、彼らはこのネットワークを修正しようとする場合、それをタッチする回数の最小数を必要と?
入力
フラグメントは、1からnまでの番号。

nは整数、最初の行、2行目の数nは、0または1であり、iはフラグメント値のi番目の数を表す状態。

次は、2つの数のN-1行は、x、yはXを表し、yは接続片。

出力

衝突の最小の数を表す数が必要なライン。

サンプル入力

11
0 0 0 1 1 0 1 0 0 1 1
1 2
1 3
2 4
2 5
5 6
5 7
3 8
3 9
3 10
9 11

サンプル出力

2

ヒント

サンプルについて説明します。まず破片III、VIに触れ、その後の作品に触れ、この状態値のすべての部分は、二回のタッチの1になります。

データ範囲を次のように

データの20%を、n≤10

データの100%、n≤5×10 5

思考

タイトル手段否定同じ色のタッチポイントの通信ブロックを表明した後、ツリー全体をカラーで触れていることを何回お願いします。

すべてのタッチを列挙するために暴力プログラムは、20ポイントを獲得しました。

より高い目標のために、第1の通信ブロックは点に縮小することができることが分かります。

次は、私たちが説明したい、この質問に対する答えはdが縮小した後、木の直径である⌊d+12⌋、です。

ツリー収縮点の後、黒と白(黒及び01の代わりに仮白)白色階層ツリーにツリー全体は、我々は、任意の時点でタッチこの点を行い、上から下に同じ色になる、再びポイントを縮小します以下前より2までの木の直径ました。したがって、その後⌊d+12⌋することに注意する必要がありますし、この説明の下限、答えは下界、木の直径マイナス2を構成します。

ツリーのポイントを見つけ、⌊d+12⌋を超えていない他のすべての点の距離にこのポイントになります。この点は、それ以外の長さd、⌊d+12⌋+⌊d+12⌋+ 1> Dの直径と矛盾するだろう見つかるはずです。

答えは⌊d+12⌋であるように、我々は、唯一のポイントか2ポイント、もう一度触れ最大で最後まで、この時点結露ポイント、毎回2削減木の直径に触れ続けます。

複雑さはO(N)です。

コード

#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct edge
{
    int to,nxt;
} e[1000010],eg[1000010];
int n,a[500010],head[500010]= {0};
int tot=0,col[500010]= {0};
int cnt=0,dep[500010],ghead[500010]= {0};
void dfs(int u,int fa)
{
    col[u]=tot;
    for(int i=head[u]; i; i=e[i].nxt)
    {
        int v=e[i].to;
        if(v==fa)
            continue;
        if(a[v]==a[u])
            dfs(v,u);
    }
    return;
}
void dfs(int u,int fa,int d)
{
    dep[u]=d;
    for(int i=ghead[u]; i; i=eg[i].nxt)
    {
        int v=eg[i].to;
        if(dep[v]) continue;
        dfs(v,u,d+1);
    }
    return;
}
int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
        scanf("%d",&a[i]);
    for(int i=1; i<n; i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        e[i]=(edge)
        {
            v,head[u]
        };
        head[u]=i;
        e[n+i]=(edge)
        {
            u,head[v]
        };
        head[v]=n+i;
    }
    for(int i=1; i<=n; i++)
        if(!col[i])
            tot++,dfs(i,0);
    for(int u=1; u<=n; u++)
        for(int i=head[u]; i; i=e[i].nxt)
        {
            int v=e[i].to;
            if(col[u]==col[v])
                continue;
            eg[++cnt]=(edge)
            {
                col[v],ghead[col[u]]
            };
            ghead[col[u]]=cnt;
            eg[++cnt]=(edge)
            {
                col[u],ghead[col[v]]
            };
            ghead[col[v]]=cnt;
        }
    memset(dep,0,sizeof(dep));
    dfs(1,0,1);
    int id=1;
    for(int i=2; i<=tot; i++)
        if(dep[i]>dep[id])
            id=i;
    memset(dep,0,sizeof(dep));
    dfs(id,0,1);
    int maxn=0;
    for(int i=1; i<=tot; i++)
        maxn=max(maxn,dep[i]);
    printf("%d\n",maxn/2);
    return 0;
}

703元記事公開 ウォンの賞賛392 ビューに14万+を

おすすめ

転載: blog.csdn.net/Eric1561759334/article/details/100687520