CF605B

大意:
给出n个点,m条边,给出m条边的权值以及这条边是否是最小生成树的边。问能否构建出这颗最小生成树,能的话输出每条边连接哪两个点
思路:
构建一个“菊花图”,即1连2,3,4,5....
然后对于每个没被选的边,就连到2与3,2与4,2与5...3与4....
注意假如一条边没被选且被连到2和3之间,那么这条边一定要比1与2、1与3之间的边要大,如何保证呢?先将边排序即可,如果权相同就先排被选了的边

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;
typedef long long LL;
int n, m;
struct node {
    int w, k, pos;
} a[N];

bool cmp(node a, node b) {
    if (a.w == b.w) return a.k > b.k;
    return a.w < b.w;
}
pair<int, int> res[N];
int main() {
    cin >> n >> m;
    for (int i = 1; i <= m; i++) cin >> a[i].w >> a[i].k, a[i].pos = i;
    sort(a + 1, a + 1 + m, cmp);
    int cnt = 1;
    int l = 2, r = 3;
    for (int i = 1; i <= m; i++) {
        if (a[i].k) {
            res[a[i].pos] = {1, ++cnt};
            //cout << res[a[i].pos].first << ' ' << res[a[i].pos].second << endl;
            if (cnt > n) {
                cout << -1 << endl;
                return 0;
            }
        } else {
            if (r > cnt) {
                cout << -1 << endl;
                return 0;
            } else {
                res[a[i].pos].first = l, res[a[i].pos].second = r;
                //cout << l << ' ' << r;
                l++;
                if (l == r) r++, l = 2;
            }
        }
    }
    if (cnt != n) {
        cout << -1 << endl;
        return 0;
    }
    for (int i = 1; i <= m; i++) {
        cout << res[i].first << ' ' << res[i].second << endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/14619426.html