2018四川省大学程序设计竞赛(ACM)I.Island

I: Island


Time Limit: 2000 MS Memory Limit: 1048576 KB

Total Submit: 117 Accepted: 9 Page View: 265

Rinne dreads sunlight, so she wants to find a refuge with the weakest sunlight. The place where Rinne stay now can be described as a tree with nn vertices. A tree is an undirected graph where any two vertices are connected by exactly one simple path. Rinne can stand on any one of the vertices. Each vertex in the tree has a value susu indicating the light intensity.

If Rinne stands on vertex ii, the light intensity she will suffer is calculated as followed.

1. We delete vertex ii and its adjacent edges in the tree, and then the tree becomes several connected components.

2. The light intensity of a component is the sum of light intensity of all vertices within it.

3. The maximum light intensity among all of the components is the light intensity that Rinne will suffer.

Rinne wants to ensure the light intensity she will suffer as less as possible. Can you help her?

The first line contains a integer TT representing the number of test cases.In each test case, the first line contains one positive integer nn.The second line contains nn integers. The ithi−th integer sisi represents the light intensity of vertex ii.The following n1n−1 lines each contains two integers u;vu;v representing that there is an undirected edge connecting vertex uu and vv. It is guaranteed that the input graph is a tree.• 1T,n2×105,0si2×105,1u;vn1≤T,∑n≤2×105,0≤si≤2×105,1≤u;v≤n
For each test case, output the minimum light intensity Rinne will suffer.

Sample Input

1

10

4 7 5 8 9 2 6 0 1 3

1 2

1 3

2 4

5 2

3 6

3 7

4 8

4 9

5 10


Sample Output

17


题意:T组数据,n个点,n-1条边。枚举每个点,拿去此点后生成的几个树的权最大值的最小值,输出最小值。

思路:两遍dfs,第一遍取任意一点作为根节点遍历,求两个东西1、该节点和其子树权值总和存入val[]。2、求该节点的所有子树中最大权值存入M[]。第二遍遍历每个点,比较M[i]和总权值与该点总权值的差(val[1] - val[x]),取其大者存入ans[]。


#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

const int MaxN = 2e5;
typedef long long LL;
typedef unsigned long long ULL;

int pre[MaxN + 5],last[MaxN + 5],other[MaxN + 5],cost[MaxN + 5],vis[MaxN + 5],seq[MaxN + 5];
int T,n,all;

LL val[MaxN+5], ans[MaxN+5], M[MaxN+5];
LL Min;


void Build(int x,int y){
	pre[++all] = last[x];
	last[x] = all;
	other[all] = y;
}

void dfs1(int x){
	int ed,dr;
	M[x] = -(1LL << 60);
	ed = last[x];
	while(ed != -1){
		dr = other[ed];
		if(!vis[dr]){
			vis[dr] = 1;
			dfs1(dr);
			val[x] += val[dr];
			if(M[x] < val[dr]) M[x] = val[dr];
		}
		ed = pre[ed];
	}
	val[x] += cost[x];
}

void dfs2(int x){	
	int ed,dr;
	ed = last[x];
	while(ed != -1){
		dr = other[ed];
		if(!vis[dr]){
			vis[dr] = 1;
			dfs2(dr);
		}
		ed = pre[ed];
	}
	if(M[x] > val[1] - val[x])ans[x] = M[x];
	else ans[x] = val[1] - val[x];
}

int main(){
	scanf("%d",&T);
	while(T--){
		Min = (1LL << 60);
		all = -1;
		scanf("%d",&n);
		for(int i = 1;i <= n;i++){
			scanf("%d",&cost[i]);
			last[i] = -1;
		}
		for(int i = 1;i <= n-1;i++){
			int a,b;
			scanf("%d%d",&a,&b);
			Build(a,b);
			Build(b,a);
		}
		vis[1] = 1;
		dfs1(1);
		for(int i = 1;i <= n; i++)vis[i] = 0;
		vis[1] = 1;
		dfs2(1);
		for(int i = 1;i <= n;i++){
			Min = min(ans[i],Min);
		}
		printf("%lld\n",Min);
		for(int i = 1; i <= n; i++){
			cost[i] = vis[i] = 0;
			ans[i] = M[i] = val[i] = 0LL;
		}
		for(int i = 0 ;i <= all; i++) {
			pre[i] = 0;
			other[i] = 0;
		}
	}
}


坑点:这道题可能给你2e5组数据,每组数据n = 1,每次全部清零会T。所以每组数据清零时用多少清多少。

你可能感兴趣的:(dfs)