HDU 6060 RXD and dividing [想法题]

来源:互联网 发布:软件项目管理 书 编辑:程序博客网 时间:2024/06/01 07:18

题意:给一个n个节点的树,要求将2-n号节点分成k部分,然后将每一部分加上节点1,每一个子树的val为最小斯坦纳树,求总的最大val

题解:想法题 = =,对于每一个子树,我们将子树中的每一个节点分到不同的集合的时候,所需要的边权是最大的,所以我们考虑每一刻子树它的节点数和k的大小,这个值就是这个子树连接它父亲的边的经过的总次数。

AC代码:

#include<stdio.h>#include<string.h>#include<algorithm>#include<queue>#define N 1000005#define mo 1000000007using namespace std;typedef long long ll;ll n,head[N],p[N][30],now,k,sum;struct edge{    ll to,next,val;}e[N*2];void init(ll x,ll y,ll v){    e[++now].to=x,e[now].val=v,e[now].next=head[y],head[y]=now;    e[++now].to=y,e[now].val=v,e[now].next=head[x],head[x]=now;}struct node{    ll id;    ll son,cost;    bool operator <(const node &x) const{        return cost<x.cost;    }}nod[N],nc;void dfs(ll x,ll from){    nod[x].id=x;    nod[x].son=1;    for(ll i=head[x];~i;i=e[i].next){        if(e[i].to==from)continue;        dfs(e[i].to,x);        sum+=e[i].val*min(nod[e[i].to].son,k);        nod[x].son+=nod[e[i].to].son;    }}int main(){    ll x,y,cur,v;    while(scanf("%lld%lld",&n,&k)!=EOF){        memset(head,-1,sizeof(head));        now=0;        sum=0;        for(ll i=1;i<n;i++)nod[i].son=0;        for(ll i=1;i<n;i++){            scanf("%lld%lld%lld",&x,&y,&v);            init(x,y,v);        }        dfs(1,0);        printf("%lld\n",sum);    }    return 0;}