POJ1112 Team Them UP!

题面

你的任务是以下列方式将一些人分成两个小队:

1、每个人都属于其中一个团队;
2、每个团队至少有一名成员;
3、团队中的每个人都认识团队中的每个人;
4、团队的规模尽可能接近。

此任务可能有许多解决方案,你可以输出任何一种解决方案,或声明解决方案不存在。

输入格式

第一行包含整数N,表示共有N个人,他们被编号为1,2,…,N。

接下来N行,第 i 行包含多个用空格分隔开的整数,表示编号为i的人认识的人的编号列表,最后以0结尾。

注意A认识B不代表B一定认识A。

输出格式

如果不存在解决方案,则输出”No solution”。

如果存在,则输出两个队伍的成员信息,每个队伍占一行,首先输出队伍的人数,然后依次输出队伍成员的编号。

数据范围

2≤N≤100

输入样例:

5
2 3 5 0
1 4 5 3 0
1 2 5 0
1 2 3 0
4 3 2 1 0

输出样例:

3 1 3 5
2 2 4

题解

明显的建反边, 染色分组, 然后为了使得两队人数差最小, 用背包

但是! 我们可以贪心!

我们按照每次染色后的两组的差值排序, 从大到小, 贪心选就好了

小生bb, 都0202年了, poj还不支持c++11吗?

代码

int h[N][N], v[N];
vector<pair<VI, VI > > ans;

bool dfs(int x, int c) {
    if (c == 1) v[x] = 1, ans.back().fi.pb(x);
    else v[x] = 2, ans.back().se.pb(x);
    rep (y, 1, n) {
        if (!h[x][y] || v[y] == 3 - c) continue;
        if (v[y] && v[y] == c) return 1;
        if (dfs(y, 3 - c)) return 1;
    }
    return 0;
}

bool cmp(const pair<VI, VI> &a, const pair<VI, VI> &b) {
    return abs((int)a.fi.size() - (int)a.se.size()) > abs((int)b.fi.size() - (int)b.se.size());
}

int main() {
    IOS; cin >> n;
    rep (i, 1, n) rep (j, i + 1, n) h[i][j] = h[j][i] = 1;
    rep (i, 1, n) while (cin >> m, m) h[i][m] = 0;
    rep (i, 1, n) rep (j, 1, n) if (h[i][j]) h[j][i] = 1;
    rep (i, 1, n) 
        if (!v[i]) {
            ans.pb({ VI(), VI() });
            if (dfs(i, 1)) { cout << "No solution"; return 0;}
        }
    sort(all(ans), cmp);
    VI &a = ans[0].fi, &b = ans[0].se;
    for (int i = 1; i < ans.size(); ++i)
        if (ans[i].fi.size() >= ans[i].se.size())
            if (a.size() >= b.size()) a.insert(a.end(), all(ans[i].se)), b.insert(b.end(), all(ans[i].fi));
            else b.insert(b.end(), all(ans[i].se)), a.insert(a.end(), all(ans[i].fi));
        else
            if (a.size() >= b.size()) b.insert(b.end(), all(ans[i].se)), a.insert(a.end(), all(ans[i].fi));
            else a.insert(a.end(), all(ans[i].se)), b.insert(b.end(), all(ans[i].fi));
    sort(all(a)); sort(all(b));
    cout << a.size(); rep (i, 0, a.size() - 1) cout << ' ' << a[i];
    cout << '\n' << b.size(); rep (i, 0, b.size() - 1) cout << ' ' << b[i];
    return 0;
}
posted @ 2020-12-16 13:29  洛绫璃  阅读(68)  评论(0编辑  收藏  举报