状态中的k就是用来区分不合法状况的,当k为0时只允许后两种情况;为时允许所有四种情况。动态规划过程计算完毕之后,还要注意最优路径可能跨立两棵子树,我们需要枚举两棵子树的路径,把它们接合。如果这两条路径的陷阱总数不到C,那么就对端点特性没有要求(四种情况均可),对应了代码中的if
(j+k < c) ans = max(ans, dp[u][j][1] +
dp[v][k][1]);;如果总数等于C`,那么路径的一端必须是陷阱。
#define PB push_back #define MP make_pair #define fi first #define se second #define EACH(i, a) for (VI::iterator i = (a).begin(); i != (a).end(); ++i) #define FOR(i, a, b) for (int i = (a); i < (b); i++) #define REP(i, n) FOR(i, 0, n) #define ZERO(a) memset(a, 0, sizeof a)
constint N = 50000; VI e[N]; int c, ans, trap[N], val[N], dp[N][4][2];
/* * dp[][][0]: entering subtree * no further points beyond the end point * * dp[][][1]: leaving subtree * further points allowed beyond the end point */
intRI() { int x; scanf("%d", &x); return x; }
voiddfs(int u, int p) { dp[u][trap[u]][0] = dp[u][trap[u]][1] = val[u]; ans = max(ans, val[u]); EACH(i, e[u]) { int v = *i; if (v == p) continue; dfs(v, u); FOR(j, trap[u], c+1) FOR(k, trap[v], c-j+1) { if (j < c) ans = max(ans, dp[u][j][1] + dp[v][k][0]); if (k < c) ans = max(ans, dp[v][k][1] + dp[u][j][0]); if (j+k < c) ans = max(ans, dp[u][j][1] + dp[v][k][1]); } FOR(j, trap[u], c+1) { dp[u][j][1] = max(dp[u][j][1], dp[v][j-trap[u]][1] + val[u]); if (j > trap[u]) dp[u][j][0] = max(dp[u][j][0], val[u] + dp[v][j-trap[u]][0]); } } }
intmain() { int cases = RI(); while (cases--) { int n = RI(); c = RI(); REP(i, n) { e[i].clear(); val[i] = RI(); trap[i] = RI(); } REP(i, n-1) { int u = RI(), v = RI(); e[u].PB(v); e[v].PB(u); } ans = 0; ZERO(dp); dfs(0, -1); printf("%d\n", ans); } }
#define REP(i, n) for (int i = 0; i < (n); i++) #define REP1(i, n) for (int i = 1; i <= (n); i++) #define FOR(i, a, b) for (int i = (a); i < (b); i++) #define ROF(i, a, b) for (int i = (b); --i >= (a); )
constint N = 20; i64 f[2][N+1];
intmain() { char a[N+1]; while (gets(a)) { int n = strlen(a); f[0][0] = 1; REP(i, n) { i64 *g = f[i&1], *h = f[i+1&1]; fill_n(h, i + 2, 0); if (a[i] == '+') REP(j, i + 1) { h[j+1] += g[j]; h[j] += g[j] * j; } else REP(j, i + 1) { h[j] += g[j] * j; if (j) h[j-1] += g[j] * j * j; } } printf("%" PRId64"\n", f[n&1][0]); } }
#define REP(i, n) for (int i = 0; i < (n); i++) #define REP1(i, n) for (int i = 1; i <= (n); i++) #define FOR(i, a, b) for (int i = (a); i < (b); i++) #define ROF(i, a, b) for (int i = (b); --i >= (a); ) #define fi first #define se second typedef pair<int, int> PII;
intRI() { int x; scanf("%d", &x); return x; }
#define C(x) ((x) * i64((x)+1) / 2 % MOD) #define NORM(x) (((x) % MOD + MOD) % MOD) #define ADD(x, y) x = ((x) + (y)) % MOD
constint N = 1000, MOD = 1000000007; PII a[N+1]; set<int> S;
#define PB push_back #define MP make_pair #define fi first #define se second #define EACH(i, a) for (VI::iterator i = (a).begin(); i != (a).end(); ++i) #define FOR(i, a, b) for (int i = (a); i < (b); i++) #define REP(i, n) FOR(i, 0, n)
const int N = 100000; int size[N]; VI e[N]; i64 ans;
int RI() { int x; scanf("%d", &x); return x; }
int RI(int &x) { return scanf("%d", &x); }
pair<i64, i64> dfs(int u, int p) { pair<i64, i64> s(0, 0); EACH(i, e[u]) { int v = *i; if (v == p) continue; pair<i64, i64> c = dfs(v, u); ans += s.se * c.fi + (s.fi + 1) * c.se; s.se += c.se + s.fi * c.fi; s.fi += c.fi; } s.fi++; return s; }
int main() { int n; while (RI(n) == 1) { REP(i, n) e[i].clear(); REP(i, n - 1) { int u = RI() - 1, v = RI() - 1; e[u].PB(v); e[v].PB(u); } ans = 0; dfs(0, -1); printf("%" PRId64 "\n", ans); } }