1. 程式人生 > >hdu6060 RXD and dividing 貪心

hdu6060 RXD and dividing 貪心

iostream clu lan 並集 blank pri print mod str

/**
題目: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的父節點相連的那條邊權最多加num次。

所以每個節點x與父節點相連的邊的權值w的貢獻為min(num,k)*w; num為以x為根的子樹的總結點數。

*/ #include<iostream> #include<cstdio> #include<algorithm> #include<map> #include<vector> #include<queue> #include<set> #include<cstring> #include<time.h> #include<random> #include<cmath> using namespace std; typedef pair<int,int> P; typedef
long long LL; const int mod = 1e9+7; const int INF = 0x3f3f3f3f; const int maxn = 1e6+100; int n, k; vector<P> G[maxn]; struct node { int sum; int w; }t[maxn]; void dfs(int r,int f) { int len = G[r].size(); t[r].sum = 1; for(int i = 0; i< len; i++){ if(G[r][i].first==f) continue
; dfs(G[r][i].first,r); t[G[r][i].first].w = G[r][i].second; t[r].sum += t[G[r][i].first].sum; } } int main() { while(scanf("%d%d",&n,&k)==2) { for(int i = 1; i <= n; i++) G[i].clear(); int u, v, w; for(int i = 1; i < n; i++){ scanf("%d%d%d",&u,&v,&w); G[u].push_back(P(v,w)); G[v].push_back(P(u,w)); } dfs(1,-1); LL ans = 0; for(int i = 2; i <= n; i++){ ans = (ans+(LL)min(t[i].sum,k)*t[i].w); } printf("%lld\n",ans); } return 0; }

hdu6060 RXD and dividing 貪心