BZOJ2314 士兵的放置

树形DP,恩然后就不会了。。。

先写了个错的离谱程序。。。果然WA了

然后开始乱搞,欸,对了!

令f[i], g[i], h[i]分别表示i号节点自己放士兵,被儿子上的士兵控制,不被儿子上的士兵控制但被父亲上的士兵控制的情况下,以i为子树中最少的士兵数

F[i], G[i], H[i]表示对应的方案数,然后这方程写的沁人心脾。。。看程序吧

 1 /**************************************************************
 2     Problem: 2314
 3     User: rausen
 4     Language: C++
 5     Result: Accepted
 6     Time:3224 ms
 7     Memory:99512 kb
 8 ****************************************************************/
 9  
10 #include <cstdio>
11 #include <algorithm>
12  
13 using namespace std;
14 typedef long long ll;
15 const int N = 5e5 + 5;
16 const int inf = 1e9;
17 const int mod = 1032992941;
18 const int Maxlen = N * 15;
19  
20 struct edge {
21     int next, to;
22     edge() {}
23     edge(int _n, int _t) : next(_n), to(_t) {}
24 } e[N << 1];
25  
26 int n;
27 int first[N], tot;
28 ll f[N], g[N], h[N];
29 ll F[N], G[N], H[N];
30 ll ans;
31 bool vis[N];
32 char buf[Maxlen], *c = buf;
33 int Len;
34  
35 inline int read() {
36     int x = 0;
37     while (*c < '0' || '9' < *c) ++c;
38     while ('0' <= *c && *c <= '9')
39         x = x * 10 + *c - '0', ++c;
40     return x;
41 }
42  
43 inline void Add_Edges(int x, int y) {
44     e[++tot] = edge(first[x], y), first[x] = tot;
45     e[++tot] = edge(first[y], x), first[y] = tot;
46 }
47  
48 #define y e[x].to
49 void dfs(int p) {
50     int x, mn;
51     ll t;
52     vis[p] = 1;
53     f[p] = 1, g[p] = inf, h[p] = 0;
54     F[p] = G[p] = H[p] = 1;
55     for (x = first[p]; x; x = e[x].next)
56         if (!vis[y]) {
57             dfs(y);
58              
59             mn = min(min(f[y], g[y]), h[y]), t = 0;
60             if (f[y] == mn) t += F[y];
61             if (g[y] == mn) t += G[y];
62             if (h[y] == mn) t += H[y];
63             f[p] += mn, (F[p] *= t) %= mod;
64              
65             mn = min(min(g[p] + f[y], g[p] + g[y]), h[p] + f[y]), t = 0;
66             if (g[p] + f[y] == mn) t += G[p] * F[y];
67             if (g[p] + g[y] == mn) t += G[p] * G[y];
68             if (h[p] + f[y] == mn) t += H[p] * F[y];
69             g[p] = mn, G[p] = t % mod;
70              
71             h[p] += g[y], (H[p] *= G[y]) %= mod;
72         }
73 }
74 #undef y
75  
76 int main() {
77     Len = fread(c, 1, Maxlen, stdin);
78     buf[Len] = '';
79     int i, x, y;
80     n = read();
81     for (i = 1; i < n; ++i) {
82         x = read(), y = read();
83         Add_Edges(x, y);
84     }
85     dfs(1);
86     printf("%lld
", min(f[1], g[1]));
87     printf("%lld
", f[1] == g[1] ? (F[1] + G[1]) % mod : f[1] < g[1] ? F[1] : G[1]);
88     return 0;
89 }
View Code
By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
原文地址:https://www.cnblogs.com/rausen/p/4296934.html