HDU 6060 RXD and dividing

Mr_Treeeee發表於2020-04-06

RXD and dividing

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 1253    Accepted Submission(s): 527


Problem Description
RXD has a tree T, with the size of n. Each edge has a cost.
Define f(S) as the the cost of the minimal Steiner Tree of the set S on tree T
he wants to divide 2,3,4,5,6,n into k parts S1,S2,S3,Sk,
where Si={2,3,,n} and for all different i,j , we can conclude that SiSj=
Then he calulates res=ki=1f({1}Si).
He wants to maximize the res.
1kn106
the cost of each edge[1,105]
Si might be empty.
f(S) means that you need to choose a couple of edges on the tree to make all the points in S connected, and you need to minimize the sum of the cost of these edges. f(S) is equal to the minimal cost 
 

Input
There are several test cases, please keep reading until EOF.
For each test case, the first line consists of 2 integer n,k, which means the number of the tree nodes , and k means the number of parts.
The next n1 lines consists of 2 integers, a,b,c, means a tree edge (a,b) with cost c.
It is guaranteed that the edges would form a tree.
There are 4 big test cases and 50 small test cases.
small test case means n100.
 

Output
For each test case, output an integer, which means the answer.
 

Sample Input
5 4 1 2 3 2 3 4 2 4 5 2 5 6
 

Sample Output
27
 

Source
 
題意:
有n個頂點,給你n-1條邊,讓你在把(2-n)頂點分成k個部分(也可以分成1到k-1個部分),每個部分和樹根頂點1組成一顆樹,求這k個樹的邊權制總和最大。

POINT:
n個頂點,和n-1條邊,證明給你的樹就是最小生成樹,那麼無論你怎麼分,其實都是最小生成樹,所以題目裡的最小斯坦納樹是沒什麼用的。
我們要求的是總和最大,我們就讓每個邊使用次數最多。易得每個邊(x和他的父親節點形成的邊)使用次數max=min(k,size[x])。
那麼答案就是sum(每個邊的權制*min(k,size[x]))。

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <math.h>
using namespace std;
#define  LL long long
const int N = 1e6+5;
int pre[N],head[N];
struct node
{
    int v,nxt,w;
}len[N<<1];
int sum[N];
int cnt;
void add(int u,int v,int w)
{
    cnt++;
    len[cnt].v=v;
    len[cnt].nxt=head[u];
    len[cnt].w=w;
    head[u]=cnt;
}
void dfs(int u,int p)
{
    sum[u]=1;
    for(int i=head[u];i!=-1;i=len[i].nxt)
    {
        if(len[i].v==p) continue;
        pre[len[i].v]=len[i].w;
        dfs(len[i].v,u);
        sum[u]+=sum[len[i].v];
    }
}
int main()
{
    int n,k;
    while(~scanf("%d %d",&n,&k))
    {
        cnt=0;
        memset(head,-1,sizeof head);
        memset(sum,0,sizeof sum);
        memset(pre,0,sizeof pre);
        for(int i=1;i<n;i++)
        {
            int u,v,w;
            scanf("%d %d %d",&u,&v,&w);
            add(u,v,w);
            add(v,u,w);
        }
        LL ans=0;
        dfs(1,-1);
        for(int i=2;i<=n;i++)
        {
            ans+=(LL)(1LL*pre[i]*1LL*min(k,sum[i]));
        }
        printf("%lld\n",ans);
    }
    
}