poj-2342
题目链接:http://poj.org/problem?id=2342
很简单的树形dp,状态方程是:
dp[i][1]+=dp[j][0] (在选择 i 的情况,j 是 i 的下属 )
dp[i][0]+=max(dp[j][0],dp[j][1]) (在不选择 i 的情况,i的下属 j 可选可不选 )
ac code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
#define N 30005
struct edge {
int v;
struct edge* f;
};
edge* a[N];
vector<int>b[N];
int dp[N][2];
int n, root;
void trees(int edg) {
if (b[edg].size() == 0) {
return;
}
for (int i = 0; i < b[edg].size(); i++) {
trees(b[edg][i]);
dp[edg][1] += dp[b[edg][i]][0];
dp[edg][0] += max(dp[b[edg][i]][0], dp[b[edg][i]][1]);
}
}
int main() {
int L, K;
memset(dp, 0, sizeof(dp));
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
a[i] = new edge;
a[i]->f = NULL;
}
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]->v);
}
while (~scanf("%d%d", &L, &K) && !(L == 0 && K == 0)) {
a[L]->f = a[K];
b[K].push_back(L);
}
for (int i = 1; i <= n; i++) {
dp[i][1] = a[i]->v;
if (a[i]->f == NULL) {
root = i;
}
}
trees(root);
cout << max(dp[root][1], dp[root][0]) << endl;
return 0;
}
codeforces Round #525(Div 2)E
题目链接:http://codeforces.com/contest/1088/problem/E
题解:
ac code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<set>
#include<vector>
#include<queue>
using namespace std;
#define N 300005
long long dp[N];
int n, a[N];
long long sum = -1e9;
int k = 0;
vector<int>q[N];
void dfs(int root, int p, int l) {
dp[root] = a[root];
for (int i = 0; i < q[root].size(); i++) {
if (q[root][i] != p) {
dfs(q[root][i], root, l);
if (dp[q[root][i]] > 0) {
dp[root] += dp[q[root][i]];
}
}
}
if (l) {
sum = max(sum, dp[root]);
//cout << sum << " " << root << endl;
}
else {
if (dp[root] == sum) {
dp[root] = 0;
k++;
}
}
}
int main() {
int u, v;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
for (int i = 1; i < n; i++) {
scanf("%d%d", &u, &v);
q[u].push_back(v);
q[v].push_back(u);
}
dfs(1, 0, 1);
dfs(1, 0, 0);
printf("%I64d %d", sum*k, k);
return 0;
}