【Gdgzezoi]問題C:ネットワークケーブルを解体します

[問題の説明]

国間のペンギンインターネットはツリー構造が形成され、ケーブルネットワークによって相互接続されています。さて冬、暖房部門燃料の不足は、そう、彼らは燃料を行うには、ネットワークケーブルの一部を解体することを決めました。しかし、今、彼らは(戦う同じ部屋に2羽のペンギンを)別の部屋を手配Kペンギンを配置する必要がありますので、Kは、その後、ケーブルの一部を削除したが、各ペンギンいることを確認する必要があり、インターネットや他の人にオンラインゲームをペンギンがありますケーブルを介して少なくとも滞在し、少なくとも一つの他のペンギンのオンラインゲームですることができます。

そこで、彼らは保持されるネットワークケーブルの必要性の最小数を知りたいですか?

[入力形式]

T整数最初の行は、データセットの数を示します。

二つの整数N、Kの各セットの最初の行は、部屋番号とペンギンの総数を表します。

N-1の整数の第2行、Aiはi番目表すI + 1とあい室整数ルームは、ケーブル接続(1≤Ai≤i)を有しています。

[出力形式]

各出力データケーブルの整数の最小数を保持表します。

[サンプル入力】

2

4 4

1 2 3

4 3

1 1 1

[サンプル出力]

2

2

[データ範囲]

データの30%:N≤15。

データの50%:N≤300。

データの70%の場合:N≤2000。

2≤K≤N≤100000、T≤10:データの100%に。

思考

片側は、二つのペンギン局、例えば点、良好であることができます。

点はANS、ANS *2≥k、のみ(K + 1)/ 2のエッジ上にある場合。

それ以外の場合は、必要ANS +(K-ANS * 2)側です。

さて問題は、どのくらいこの点を追求するために変換されます。

DP [I] [0]私をルートとするサブツリー内のポイントの最大数は2つずつのペアリングが可能であり、それはノードIが含まれていない表します。

DP [i]が[1]私は2つずつペアリングすることが可能であるルートとするサブツリー内のポイントの最大数を表し、ノードは、Iを含みます。

伝達方程式:

DP [U] [0] =ΣVUは息子DP [V] [1]です。

DP [U] [1] = MAX(DP [U] [1]、DP [U] [0] -dp [V] [1] + DP [V] [0] +2)。

最終的にはMAX(DP [1] [0]、DP [1] [1])はANSです。

コード

#include<bits/stdc++.h>
using namespace std;
const int N=100077; 
struct E
{
    int to,next;
}e[N*2];
int ls[N],cnt;
   
void add(int x,int y)
{
    e[++cnt].to=y; e[cnt].next=ls[x]; ls[x]=cnt;
}
   
int n,K;
int f[N][2];
   
void dfs(int u,int last)
{
    f[u][0]=f[u][1]=0;
    for (int i=ls[u];i;i=e[i].next){
        int v=e[i].to;
        if (v!=last){
            dfs(v,u);
            f[u][0]+=f[v][1];
        }
    }
    for (int i=ls[u];i;i=e[i].next){
        int v=e[i].to;
        if (v!=last){
            f[u][1]=max(f[u][1],f[u][0]-f[v][1]+f[v][0]+2);
        }
    }
    return;
}
   
int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        memset(ls,0,sizeof(ls));
        cnt=0;
        scanf("%d%d",&n,&K);
        int x,y;
        for (int i=1;i<n;i++)
        {
            scanf("%d",&x);
            add(i+1,x);
            add(x,i+1);
        }
        dfs(1,0);
        int tmp=max(f[1][0],f[1][1]);
        if (K<=tmp)
        {
            printf("%d\n",(K+1)/2);
        }
        else
        {
            printf("%d\n",K-tmp/2);
        }
    }
    return 0;
}
703元記事公開 ウォンの賞賛392 ビューに14万+を

おすすめ

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