Codeforces Round #245 (Div. 1)——Guess the Tree

来源:互联网 发布:mac虚拟机 360优化 编辑:程序博客网 时间:2024/05/22 03:28

题目链接

  • 题意:
    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++);elseit++;}mp[Node(ipt[i])]++;}if (mp.size() != 1 || mp.begin()->second != 1) ok = false;if (ok) puts("YES");else puts("NO");}return 0;}



2 0
原创粉丝点击