TopCoder SRM 658 Div1 300 - OddEvenTree (树的性质 + 构造)

来源:互联网 发布:专科学软件专业 编辑:程序博客网 时间:2024/05/18 00:37

题意

给出任意两点之间的距离的奇偶性,问存不存在这样一棵树。能的话就输出。

思路

看了cgy4ever的题解(http://codeforces.com/blog/entry/17732)。

下面的思路都是自己YY的。如有错误请指出_(:3」∠)_

首先,任意的一棵树都是一个二分图,也就是可以对一棵树进行黑白染色,黑的结点和白的结点各为一个集合。

然后我们可以得知,一个集合里的点的距离肯定都是偶数,不同集合的点之间的距离是奇数。

然后我们可以对题目给的奇偶进行检测,如果奇偶都是符合要求的,我们就可以构造出这么一个图。

现在问题就变成了如何检测奇偶的正确性。

我们可以枚举全部的结点,判断mp[i][j]是否等于mp[j][i]。
再根据两个结点所属的集合判断它们的奇偶性是不是符合要求的。

上面那步通过了,然后就是构造树了。
我们只要把1集合里的一个点拿出来,连上2集合的所有点,再随便拿一个2集合里的点,连上1集合里的所有点就行了。

代码

class OddEvenTree {    set<int> s, s1;    public:    vector<int> getTree(vector<string> x) {        int n = SZ(x);        vector<int> illegal = {-1};        vector<int> mp[100];        vector<int> ans;        for (int i = 0; i < SZ(x); i++)            for (int j = 0; j < SZ(x[i]); j++) mp[i].PB(x[i][j] == 'E' ? 0 : 1);        if (mp[0][0] != 0) return illegal;        for (int i = 0; i < SZ(mp[0]); i++)        {            if (mp[0][i]) s1.insert(i);            else s.insert(i);        }        if (s1.empty()) return illegal;        for (int i = 0; i < n; i++)            for (int j = 0; j < n; j++)            {                if (mp[i][j] != mp[j][i]) return illegal;                int x = s.count(i) ? 0 : 1;                int y = s.count(j) ? 0 : 1;                if (x == y && mp[i][j] != 0) return illegal;                else if (x != y && mp[i][j] != 1) return illegal;            }        for (auto i : s) ans.PB(i), ans.PB(*s1.begin());        for (set<int>::iterator it = ++s1.begin(); it != s1.end(); it++) ans.PB(*s.begin()), ans.PB(*it);        return ans;    }};
0 0