题目链接:点击打开链接
n个点, m条边, 给出m条边的权值以及是否在最小生成树中, 如果可以还原最小生成树, 则按照顺序输出各边, 否则输出-1.
考虑这样一种构造方法, 首先对边的权值进行排序, 如果当前边在最小生成树中, 直接将顶点加入. 否则, 为当前边分配顶点, 由于给在最
小生成树的边分配顶点时, 采用了(a, a + 1)这样的分配方式, 所以给不在最小生成树分配顶点时要避免这种方式, 加入判断条件即可.
AC代码:
#include "iostream"
#include "cstdio"
#include "cstring"
#include "algorithm"
#include "queue"
#include "stack"
#include "cmath"
#include "utility"
#include "map"
#include "set"
#include "vector"
#include "list"
#include "string"
using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e5 + 5;
int n, m, x, y, z, last;
pair<int, int> ans[MAXN];
vector<pair<pair<int, int>, int > > v;
int main(int argc, char const *argv[])
{
scanf("%d%d", &n, &m);
for(int i = 0; i < m; ++i) {
scanf("%d%d", &x, &y);
v.push_back(make_pair(make_pair(x, !y), i));
}
sort(v.begin(), v.end());
x = 2, y = 0, last = 1;
for(int i = 0; i < v.size(); ++i) {
if(!v[i].first.second) {
ans[v[i].second] = make_pair(last, last + 1);
last++;
}
else {
y++;
if(x == y + 1) {
x++;
y = 1;
}
if(x > last) {
printf("-1\n");
return 0;
}
ans[v[i].second] = make_pair(y, x);
}
}
for(int i = 0; i < m; ++i)
printf("%d %d\n", ans[i].first, ans[i].second);
return 0;
}