HDU 6060 RXD and dividing

来源:互联网 发布:基本网络知识 编辑:程序博客网 时间:2024/05/20 16:44

题目

RXD and dividing

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


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 41 2 32 3 42 4 52 5 6
 

Sample Output
27

题目大意


  给你n个点,要求你把[2-n]分成k个部分,然后每一部分最后和1连通, 计算每一部分的权重和,最后求k部分的所有权重和, 现在让我们求怎么分才能使得最后的权重和最大


解题思路


 看完题解之后感觉突然明白了,其实根本没必要去管怎么去分成k部分,我们只需要保证每条边最大限度的被使用就可以了


如图,我们只需要让a这条边走min(size[2],k)就可以,看图就可以知道a最多被走size[2]次,因为每个集合是不重复的,不可能一个点被用两次,但是还不能超过k次

所以一遍dfs就可以,只需要记录该点的size和他到父节点的权重

下面贴上代码

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>using namespace std;#define LL long long#define read(a) scanf("%d",&a)const int maxn=1e6+10;int siz[maxn];int pre[maxn];int n,k;struct tree{    int v;    int cost;    tree(){}    tree(int a,int b):v(a),cost(b){}};vector<tree> e[maxn];void dfs(int x,int fa){    siz[x]=1;    for(auto &y:e[x])    {        if(y.v==fa)            continue;        dfs(y.v,x);        pre[y.v]=y.cost;        siz[x]+=siz[y.v];    }}void work(){    int x,y,z;    memset(siz,0,sizeof(siz));    memset(pre,0,sizeof(siz));    for(int i=1;i<=n;i++)        e[i].clear();    for(int i=1;i<n;i++)    {        read(x);read(y);read(z);        e[x].push_back(tree(y,z));        e[y].push_back(tree(x,z));    }    dfs(1,-1);    LL ans=0;   /* for(int i=1;i<=n;i++)    {        cout<<i<<"  pre "<<pre[i]<<"  siz "<<siz[i]<<endl;    }*/    for(int i=1;i<=n;i++)    {       // int a=pre[i]*min(siz[i],k);       // cout<<a<<endl;        ans+=1LL*(LL)pre[i]*(LL)min(siz[i],k);    }    printf("%lld\n",ans);}int main(){    while(~scanf("%d %d",&n,&k))    {        work();    }    return 0;}


 

原创粉丝点击