多校第三場 1005 HDU 6060 思維貪心+dfs+一維建樹

RXD and dividing

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


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 4 1 2 3 2 3 4 2 4 5 2 5 6
 

Sample Output
27


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<string>
#include<cmath>
#include<vector>
#define maxlen 1000000+7

using namespace std;
vector<pair<int, int> >nextpoint[maxlen];
bool vis[maxlen];


/*
考慮每條邊對答案的貢獻,很容易可以知道能用到這條邊的最多的生成樹是從這條邊往下的點的數量,
即每個下面的點都是獨立的點集的時候。但是由於最多隻有k個集合 所以答案就是w[i]*min(k,sz[i])
對i求和

建樹用vector+pair建
統計下面節點數量用dfs + vis數組
注意結果中間運算用long long維護
*/
int n, k;
long long ans;

int dfs(int x)
{
	int cnt = 1;
	for(int i = 0; i < nextpoint[x].size(); i++)
	{
		int newpos = nextpoint[x][i].first;
		if(vis[newpos])
			continue;
		vis[newpos] = 1;
		int amount = dfs(newpos);
		//cout<<amount<<endl;
		ans += (long long)min(amount, k) * (long long)nextpoint[x][i].second;
		cnt += amount;
	}
	return cnt;
}

int main()
{
	//freopen("test.txt","r",stdin);
	while(scanf("%d %d", &n, &k) != EOF)
	{
		for(int i = 1; i <= n; i++)
			nextpoint[i].clear();
		memset(vis, 0, sizeof vis);
		ans = 0;
		for(int i = 0; i < n - 1; i++)
		{
			int x;
			int y;
			int val;
			scanf("%d %d %d", &x, &y, &val);
			nextpoint[x].push_back(pair<int, int>(y, val));
			nextpoint[y].push_back(pair<int, int>(x, val));
		}
		vis[1]=1;
		dfs(1);
		printf("%lld\n", ans);
	}

	return 0;
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章