2018 Yinchuan tournament G - Factories Gym - 102222G (tree DP)

Byteland has n cities numbered from 1 to n, and n−1 bi-directional roads connecting them. For each pair of cities, the residents can arrive one from another one through these roads (which also means the road network in Byteland is a tree).

Ghaliyah, the queen of the land, has decided to construct k new factories. To avoid contamination, she requires that a factory can locate at a city with only one road (which also means this city is a leaf in the road network). Besides, a city can only have one factory.

You, as the royal designer, are appointed to arrange the construction and meanwhile, minimize the sum of distances between every two factories.

Input
The input contains several test cases, and the first line is a positive integer T indicating the number of test cases which is up to 103.

For each test case, the first line contains two integers n (2≤n≤105) and k (1≤k≤100) indicating the number of cities in Byteland and the number of new factories which are asked to construct.

Each of the following n−1 lines contains three integers u,v (1≤u,v≤n) and w (1≤w≤105) which describes a road between the city u and the city v of length w.

We guarantee that the number of leaves in the road network is no smaller than k, and the sum of n in all test cases is up to 106.

Output
For each test case, output a line containing Case #x: y, where x is the test case number starting from 1, and y is the minimum sum of distances between every two factories.

Example
Input
2
4 2
1 2 2
1 3 3
1 4 4
4 3
1 2 2
1 3 3
1 4 4
Output
Case #1: 5
Case #2: 18

Meaning of the title:
the n-constructed tree cities. It can be arranged on the plant leaf node. K factories arrangement.
How to find the plant arrangement, such that the minimum distance between the plants and

Ideas:
the distance between the point count and can not be calculated directly, instead contribution count edge.
Dp count tree to the edge weights w a subtree corresponding point u. Assuming that the sub-tree tree arranged j points, then the contribution of this side is w * (k - j) * j.
State is defined as f [u] [k], u represents the minimum edge disposed contribution k bomb is under the root node.
Transfer equation: f [u] [i] = min (f [u] [i], f [u] [i - j] + f [v] [j] + w * (k - j) * j);

Because the factory is arranged only in a leaf node, then the initialization of f [u] [1] = 0 on the leaf nodes.
Because the recursive relationship is the same, it does not matter who is the root node. Codes do not see a lot of blog root leaf nodes when representing not understand. . .

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;
const ll INF = 1e18;
const int maxn = 1e5 + 7;
int head[maxn << 1],nex[maxn << 1],to[maxn << 1],val[maxn << 1],tot;
int deg[maxn],siz[maxn];
ll f[maxn][105];
int n,k;

void add(int x,int y,int z)
{
    to[++tot] = y;
    nex[tot] = head[x];
    val[tot] = z;
    head[x] = tot;
}

void init1()
{
    tot=0;
    for(int i = 1;i <= n;i++)
    {
        deg[i] = siz[i] = head[i] = 0;
    }
    for(int i = 1;i <= n;i++)
    {
        head[i + n] = 0;
    }
}
void init2()
{
    for(int i = 1;i <= n;i++)
    {
        f[i][0] = 0;
        for(int j = 1;j <= k;j++)f[i][j] = INF;
        if(deg[i] == 1)
        {
            f[i][1] = 0;
            siz[i] = 1;
        }
    }
}

void DP(int u,int fa)
{
    for(int i = head[u];i;i = nex[i])
    {
        int v = to[i],w = val[i];
        if(v == fa)continue;
        DP(v,u);
        siz[u] += siz[v];

        for(int i = min(k,siz[u]);i >= 1;i--)
        {
            for(int j = 1;j <= min(i,siz[v]);j++)
            {
                f[u][i] = min(f[u][i],f[u][i - j] + f[v][j] + w * (k - j) * j);
            }
        }
    }
}


int main()
{
    int T;scanf("%d",&T);
    int kase = 0;
    while(T--)
    {
        scanf("%d%d",&n,&k);
        init1();
        for(int i = 1;i < n;i++)
        {
            int x,y,z;scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);add(y,x,z);
            deg[x]++;deg[y]++;
        }

        int rt = 1;
        for(int i = 1;i <= n;i++)
        {
            if(deg[i] > 1)
            {
                rt = i;
                break;
            }
        }

        init2();
        DP(rt,0);
        printf("Case #%d: %lld\n",++kase,f[rt][k]);
    }
    return 0;
}

Published 676 original articles · won praise 18 · views 30000 +

Guess you like

Origin blog.csdn.net/tomjobs/article/details/104190561