最大子树和(洛谷-P1122)
題目描述
小明對數(shù)學(xué)飽有興趣,并且是個勤奮好學(xué)的學(xué)生,總是在課后留在教室向老師請教一些問題。一天他早晨騎車去上課,路上見到一個老伯正在修剪花花草草,頓時想到了一個有關(guān)修剪花卉的問題。于是當(dāng)日課后,小明就向老師提出了這個問題:
一株奇怪的花卉,上面共連有N朵花,共有N?1條枝干將花兒連在一起,并且未修剪時每朵花都不是孤立的。每朵花都有一個“美麗指數(shù)”,該數(shù)越大說明這朵花越漂亮,也有“美麗指數(shù)”為負(fù)數(shù)的,說明這朵花看著都讓人惡心。所謂“修剪”,意為:去掉其中的一條枝條,這樣一株花就成了兩株,扔掉其中一株。經(jīng)過一系列“修剪“之后,還剩下最后一株花(也可能是一朵)。老師的任務(wù)就是:通過一系列“修剪”(也可以什么“修剪”都不進(jìn)行),使剩下的那株(那朵)花卉上所有花朵的“美麗指數(shù)”之和最大。
老師想了一會兒,給出了正解。小明見問題被輕易攻破,相當(dāng)不爽,于是又拿來問你。
輸入輸出格式
輸入格式:
第一行一個整數(shù)N(1 ≤ N ≤ 16000)。表示原始的那株花卉上共N朵花。
第二行有N個整數(shù),第II個整數(shù)表示第II朵花的美麗指數(shù)。
接下來N-1行每行兩個整數(shù)a,b,表示存在一條連接第a朵花和第b朵花的枝條。
輸出格式:
一個數(shù),表示一系列“修剪”之后所能得到的“美麗指數(shù)”之和的最大值。保證絕對值不超過2147483647。
輸入輸出樣例
輸入樣例#1:
7
-1 -1 -1 1 1 1 0
1 4
2 5
3 6
4 7
5 7
6 7
輸出樣例#1:
3
思路:樹形dp
實質(zhì)是給一棵 n 個點的樹,以 1 號點為根,求以每個點為根的子樹大小,用 f[x] 表示以 x 為根且包含 x?的最大權(quán)聯(lián)通塊,則有狀態(tài)轉(zhuǎn)移方程:f[x]+=max(0,f[y]),其中 y 為 x 的兒子,由于兒子結(jié)點的美麗值可能小于 0,因此要與 0 逐個比較來判斷是否選擇
源代碼
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<string> #include<cstdlib> #include<queue> #include<set> #include<map> #include<stack> #include<ctime> #include<vector> #define INF 0x3f3f3f3f #define PI acos(-1.0) #define N 100000 #define MOD 16007 #define E 1e-6 #define LL long long using namespace std; struct Edge{int to;int next; }edge[N]; int n; int a[N]; int head[N],f[N]; int cnt,res; void addEdge(int x,int y){edge[++cnt].to=y;edge[cnt].next=head[x];head[x]=cnt; } void treeDP(int x,int father){f[x]=a[x];for(int i=head[x];i;i=edge[i].next){int y=edge[i].to;if(y!=father){treeDP(y,x);f[x]+=max(0,f[y]);}}res=max(res,f[x]); } int main() {scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);for(int i=1;i<n;i++){int x,y;cin>>x>>y;addEdge(x,y);addEdge(y,x);}treeDP(1,0);printf("%d",res);return 0; }?
總結(jié)
以上是生活随笔為你收集整理的最大子树和(洛谷-P1122)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 逆波兰表达式(信息学奥赛一本通-T119
- 下一篇: 训练日志 2018.10.11