Codeforces Round #245 (Div. 1)——Guess the Tree
Posted zhchoutai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #245 (Div. 1)——Guess the Tree相关的知识,希望对你有一定的参考价值。
- 题意:
n个节点,给定每一个节点的子树(包含自己)的节点个数。每一个节点假设有子节点必定大于等于2。求这种数是否存在
n (1?≤?n?≤?24).
- 分析:
- 用类似DP的思路,从已知開始。这题的已知显然是叶子,那么从叶子開始考虑。
如今给一个节点,子树节点数为x。那么从叶子中找x-1个就可以。之后再来一个y。不放设y <= x,这时候就有两种选择,尽量选1或者尽量选x。分析一下:首先明确一点。无论怎样选择,之后能用的点的和是一定的。假设尽量选小的,那么会使得选过之后的点数小的比較少。假设尽量选大的,那么之后的点数的方差比較大(表述比較抽象。事实上就是大的更大。小的还在),那么显然尽量选大的是最好的
后来发现有些瑕疵,尽量选大的可能会导致当前点无解,比方1 1 1 1 1 1 1 4 3 3 7 12这个数据
所以在选择的时候,贪心选择,假设无解再回溯就可以
const int MAXN = 50; struct Node { int x; Node (int x) : x(x) {} bool operator< (const Node& rhs) const { return x > rhs.x; } }; int ipt[MAXN]; map<Node, int>mp; map<Node, int>::iterator it; bool dfs(map<Node, int>::iterator it, int& v) { if (it == mp.end()) { if (v == 0) return true; return false; } int n = it->first.x; int num = min(v / n, it->second); FED(i, num, 0) { it->second -= i; v -= i * n; if (dfs(++it, v)) return true; v += i * n; it--; it->second += i; } return false; } int main() { // freopen("in.txt", "r", stdin); int n; while (~RI(n)) { mp.clear(); bool ok = true; int cnt = 0; REP(i, n) { int t; RI(t); if (t == 1) mp[Node(t)]++; else ipt[cnt++] = t; } sort(ipt, ipt + cnt); REP(i, cnt) { int t = ipt[i] - 1; it = mp.upper_bound(Node(t)); if (!dfs(it, t)) { ok = false; break; } it = mp.begin(); while (it != mp.end()) { if (it->second == 0) mp.erase(it++); else it++; } mp[Node(ipt[i])]++; } if (mp.size() != 1 || mp.begin()->second != 1) ok = false; if (ok) puts("YES"); else puts("NO"); } return 0; }
以上是关于Codeforces Round #245 (Div. 1)——Guess the Tree的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #245 (Div. 1)——Guess the Tree
Codeforces Round #245 (Div. 1) B. Working out
Codeforces Round #436 E. Fire(背包dp+输出路径)
[ACM]Codeforces Round #534 (Div. 2)