使用stringstream流输入和getline。简单方便,去同步后速度很快。
建图用map记录编号,有一个log。
其余就是个树上背包,注意是个森林,所以要有一个虚点0把所有根连一起。
C++ 代码
// Program written by Liu Zhaozhou ~~~
const int Maxn = 205, Maxm = 405;
int n, m, cnt = 0, head[Maxn], ver[Maxm], nxt[Maxm];
map <string, int> h; int fat[Maxn], val[Maxn], tot = 0;
inline void AddEdge(int u, int v) {
ver[++cnt] = v, nxt[cnt] = head[u], head[u] = cnt;
ver[++cnt] = u, nxt[cnt] = head[v], head[v] = cnt;
} string s, a, b; stringstream ss; int f[Maxn][Maxn], sze[Maxn];
inline void construct(void) { h.clear(); cnt = 0; Ms(head, 0); Ms(fat, 0); tot = 0; Ms(f, 0x3f); }
inline int pos(string str) { return h.find(str) == h.end() ? h[str] = ++tot : h[str]; }
inline void dp(int u) {
sze[u] = 1; f[u][0] = 0;
for (int i = head[u]; i; i = nxt[i]) {
if (ver[i] == fat[u]) continue;
dp(ver[i]); sze[u] += sze[ver[i]];
}
for (int i = head[u]; i; i = nxt[i]) {
if (ver[i] == fat[u]) continue;
for (int j = sze[u]; j; j--)
for (int k = sze[ver[i]]; k; k--)
if (j - k >= 0) chkmin(f[u][j], f[u][j - k] + f[ver[i]][k]);
} if (u) for (int i = 1; i <= sze[u]; i++) chkmin(f[u][i], val[u]);
}
signed main(void) {
// file("");
ios :: sync_with_stdio(false);
while (getline(cin, s) && s[0] != '#') {
construct(); ss.clear(); ss.str(s); ss >> n >> m;
for (int i = 1, u, v; i <= n; i++) {
getline(cin, s); ss.clear(); ss.str(s);
ss >> a; u = pos(a); ss >> val[u];
while (ss >> b) { v = pos(b); AddEdge(u, v); fat[v] = u; }
}
for (int u = 1; u <= n; u++) if (fat[u] == 0) AddEdge(u, 0);
dp(0); cout << f[0][m] << '\n';
}
// fwrite(pf, 1, o1 - pf, stdout);
return 0;
}
/**/
streamstring的用法哪里学