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;
}