HDU 6060 RXD and dividing(dfs 思维)

RXD and dividing

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

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 Si?Sj=∅. 
Then he calulates res=∑ki=1f({1}?Si).
He wants to maximize the res.
1≤k≤n≤106
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 n−1 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 n≤100.

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

2017 Multi-University Training Contest - Team 3

【题意】给你一棵树,将节点[2,n]最多分为k份,再将1节点加入到每一份,将每一份的节点连接起来,权值之和加入ans,求最大化ans。

【分析】咋一看,发现很难,不会...但看了题解后仔细一想,就是个傻逼题啊...每一个 节点与他父亲节点之间的权值的贡献就是他子树分成的份数,那我们就最大化这个份   数就是了...

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
#define mp make_pair
#define rep(i,l,r) for(int i=(l);i<=(r);++i)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 1e6+50;;
const int M = 255;
const int mod = 19260817;
const int mo=123;
const double pi= acos(-1.0);
typedef pair<int,int>pii;
int n,k,cas;
ll ans;
int sz[N];
vector<pii>edg[N];
void dfs(int u,int fa){
    sz[u]=1;
    for(auto e : edg[u]){
        int v=e.first;
        int w=e.second;
        if(v==fa)continue;
        dfs(v,u);
        sz[u]+=sz[v];
        ans+=1LL*w*min(sz[v],k);
    }
}
int main(){
    //int T;
    //scanf("%d",&T);
    while(~scanf("%d%d",&n,&k)){
        for(int i=1;i<=n;i++)edg[i].clear();
        for(int i=1,u,v,w;i<n;i++){
            scanf("%d%d%d",&u,&v,&w);
            edg[u].pb(mp(v,w));edg[v].pb(mp(u,w));
        }
        ans=0;
        dfs(1,0);
        printf("%lld\n",ans);
    }
    return 0;
}
时间: 2024-08-01 10:40:55

HDU 6060 RXD and dividing(dfs 思维)的相关文章

HDU 6060 RXD and dividing(LCA)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6060 [题目大意] 给一个n个节点的树,要求将2-n号节点分成k部分, 然后将每一部分加上节点1,求每个集合最小斯坦纳树的最大权值和. [题解] 我们按照后序遍历染色分组,得到的一定是最优分组, 现在考虑在不同颜色的虚树上求路径权值和, 我们发现每个点增加的权值是深度减去到根的路径上已被覆盖的长度, 这个长度等于与dfs序前继的LCA的深度,因此我们在搜索的同时计算与dfs序前继的LCA即可.

hdu 6060 RXD and dividing

思路:判断子树节点个数和k的最小值就好了,long long 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e6+10; 5 6 int n,k; 7 vector<pair<int ,ll > > e[N]; 8 ll sum; 9 int a[N]; 10 void dfs(int u,int fa){ 11 a[u]=1; 12 for

hdu6060 RXD and dividing 贪心

/** 题目:hdu6060 RXD and dividing 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6060 题意:贪心 给定一颗树,n个节点,编号为1~n.将2~n编号的节点分成k份. 每一份分别和编号1的节点取并集.然后求每一份的节点连通的最小边权和: 然后k份获得的边权和加起来:问:求可以获得的k份边权和的总和的最大值. 思路:通过画树容易发现,假如k无穷大,如果节点x为根的子树有num个节点,那么x与x的父节点相连的那条边权最多加nu

hdu 3709 数位dp(小思维)

http://acm.hdu.edu.cn/showproblem.php?pid=3709 Problem Description A balanced number is a non-negative integer that can be balanced if a pivot is placed at some digit. More specifically, imagine each digit as a box with weight indicated by the digit.

HDU 哈密顿绕行世界问题 (dfs)

Problem Description 一个规则的实心十二面体,它的 20个顶点标出世界著名的20个城市,你从一个城市出发经过每个城市刚好一次后回到出发的城市. Input 前20行的第i行有3个数,表示与第i个城市相邻的3个城市.第20行以后每行有1个数m,m<=20,m>=1.m=0退出. Output 输出从第m个城市出发经过每个城市1次又回到m的所有路线,如有多条路线,按字典序输出,每行1条路线.每行首先输出是第几条路线.然后个一个: 后列出经过的城市.参看Sample output

HDU 4869 Turn the pokers(思维+组合公式+快速幂)

Turn the pokers 大意:给出n次操作,给出m个扑克,然后给出n个操作的个数a[i],每个a[i]代表可以翻的扑克的个数,求最后可能出现的扑克的组合情况. Hint Sample Input: 3 3 3 2 3 For the this example: 0 express face down,1 express face up Initial state 000 The first result:000->111->001->110 The second result:0

hdu 3006 The Number of set(思维+壮压DP)

The Number of set Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1056    Accepted Submission(s): 655 Problem Description Given you n sets.All positive integers in sets are not less than 1 and

hdu6035[dfs+思维] 2017多校1

/*hdu6035[dfs+思维] 2017多校1*/ //合并色块, 妙啊妙啊 #include<bits/stdc++.h> using namespace std; const double eps=1e-8; const int inf=0x3f3f3f3f; typedef long long LL; vector<int>G[200005]; LL sum[200005]; int c[200005],son[200005],mark[200005]; int n,u,

HDU 1241 Oil Deposits --- 入门DFS

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1241 /* HDU 1241 Oil Deposits --- 入门DFS */ #include <cstdio> int m, n; //n行m列 char mapp[105][105]; /* 将和i,j同处于一个连通块的字符标记出来 */ void dfs(int i, int j){ if (i < 0 || j < 0 || i >= n || j >= m