首页 > 代码库 > Codeforces Round #245 (Div. 1)——Guess the Tree
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
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。