CF605B - Lazy Student

大意:
給出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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章