列表

详情


NC20433. [SHOI2015]聚变反应炉

描述

曾经发明了零件组装机的发明家SHTSC又公开了他的新发明:聚变反应炉--一种可以产生大量清洁能量的神秘装置 。
众所周知,利用核聚变产生的能量有两个难点:一是控制核聚变反应的反应强度,二是使用较少的能量激发聚变 反应。而SHTSC已经完美解决了第一个问题。
一个聚变反应炉由若干个相连的聚变块组成,为了能够使得聚变反应 可控,SHTSC保证任意两个聚能块都可以通过相互之间的链接到达,并且没有一个聚能块可以不重复经过一个链接 回到它自己。
但是第二个问题SHTSC还没有完全解决。在他设计的聚变反应炉当中,每个聚变块都需要一定的初始 能量di来进行激发,不过SHTSC不需要手动激发所有聚变块,这是因为一旦一个聚变块被激发,则会向与其直接相连的所有还未被激发的聚变块传送ci个单位的能量。这样后被触发的聚变块可以以更低的初始能量来激发,甚至可能不需要额外的外界能量就可自行激发,从而降低了总激发能量的消耗。现在给出了一个聚变反应炉,求至少要多少能量才能激发所有聚变块。

输入描述

第一行一个整数n。表示共有n个聚能块,由1-n编号。 
第二行n个整数,表示di。 
第三行n个整数,表示ci
以下n-1行每行两个整数,u,v。表示编号为u和v的聚能块是相连的。输入保证符合题目描述。 
Type A :ci ≤ 1,有 n ≤ 100000。 
Type B :ci ≤ 5,有n ≤ 2000。 
对于所有的数据,1 ≤ di, Sum(di) ≤ 10^9。输入保证符合题目描述。

输出描述

一行一个整数,表示至少需要多少个单位的能量才能激发所有聚变块。

示例1

输入:

5
1 1 1 1 1
1 1 1 1 1
1 2
2 3
3 4
4 5

输出:

1

说明:

//样例1:只需要触发任意一个聚变块即可激活整个聚变反应装置。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 81ms, 内存消耗: 8540K, 提交时间: 2019-11-04 18:35:31

#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
const int inf=0x3f3f3f3f;
int n,d[100005],c[100005];
int cnt,head[100005],flag;
int f[100005],g[100005],F[100005];//f 父亲 g自己 F 01背包
struct q {
	int next,to;
} e[200005];
void add(int x,int y) {
	e[++cnt].next=head[x],e[cnt].to=y,head[x]=cnt;
	e[++cnt].next=head[y],e[cnt].to=x,head[y]=cnt;
}
void dfs(int v,int fa) {
	int i,u,sc=0,j;
	for(i=head[v]; i; i=e[i].next) {
		u=e[i].to;
		if(u==fa)continue;
		sc+=c[u];
		dfs(u,v);
	}
	if(flag) {
		for(i=1; i<=sc; i++)F[i]=inf;
		F[0]=0;
		for(i=head[v]; i; i=e[i].next) {
			u=e[i].to;
			if(u==fa)continue;
			for(j=sc; j>=0; --j) {
				int a=F[j]+f[u];
				int b=j<c[u]?inf:F[j-c[u]]+g[u];
				F[j]=min(a,b);
			}
		}
		int mmin=inf;
		for(j=0; j<=sc; ++j) {
			if(j+c[fa]<=d[v]) {
				mmin=min(mmin,F[j]-j);
			} else break;
		}
		f[v]=mmin+d[v]-c[fa];
		mmin=inf;
		for(j=0; j<=sc; ++j) {
			if(j<=d[v]) {
				mmin=min(mmin,F[j]-j);
			} else break;
		}
		g[v]=mmin+d[v];
	}else{
		int t1=0,t2=0;
		for(i=head[v]; i; i=e[i].next) {
			u=e[i].to;
			if(u==fa)continue;
			if(!c[u])t1+=f[u];
			else{
				if(f[u]==g[u])t1+=g[u],t2+=c[u];
				else t1+=f[u];
			}
		}
		g[v]=t1+max(0,d[v]-t2);
		f[v]=t1+max(0,d[v]-t2-c[fa]);
	}
	return;
}
int main() {
	int i,x,y;
	scanf("%d",&n);
	for(i=1; i<=n; ++i)scanf("%d",&d[i]);
	for(i=1; i<=n; ++i){
		scanf("%d",&c[i]);
		if(c[i]>1)flag=1;
	}
	for(i=1; i<n; ++i) {
		scanf("%d%d",&x,&y);
		add(x,y);
	}
	dfs(1,0);
	printf("%d",g[1]);
}

上一题