大意:
給出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;
}