2017 Multi-University Training Contest

来源:互联网 发布:即将失效请记好新域名 编辑:程序博客网 时间:2024/05/29 19:29
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6060


题目大意: 给n个点和n-1条边, 每条边有个权值, 现在让你把2~n个点分到k个集合中, 每个点只能分到一个集合中,  在每个集合中的点和一号点形成一个最小生成树, 现在让你分这n个点, 使得k个几个的最小生成树的权值和最大。


解题思路:  对于一条边, 我们求出这条边下面的点数sz, 如果sz, 如果sz > k  这条边就会给答案贡献k次, 反之 贡献sz次。 


//2017-08-02 13:02//2017-08-02 13:29#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<queue>#include<vector>#include<algorithm>using namespace std;typedef long long LL;typedef pair<int , int> PII;const int MaxN = 1e6;vector<PII> edge[MaxN + 5];int sz[MaxN + 5], falen[MaxN + 5];int n, k;LL ans;void dfs(int u, int fa, int l){falen[u] = l;sz[u]++;for(int i = 0; i < edge[u].size(); i++){int v = edge[u][i].first;int nxtl = edge[u][i].second;if(v != fa){dfs(v, u, nxtl);sz[u] += sz[v];}}ans = ans + (LL)falen[u] * (LL)min(sz[u], k);}int main(){while(~scanf("%d %d", &n, &k)){ans = 0;memset(sz, 0, sizeof(sz));memset(falen, 0, sizeof(falen));memset(edge, 0, sizeof(edge));for(int i = 1; i < n; i++){int u, v, c;scanf("%d %d %d", &u, &v, &c);edge[u].push_back(make_pair(v, c));edge[v].push_back(make_pair(u, c));}dfs(1, 0, 0);printf("%lld\n", ans);}return 0;}


比赛的时候这道题没读懂,  也没怎么想, 结束之后听他们一讲题意才明白。



原创粉丝点击