首页 > 技术文章 > 题解 CF404C 【Restore Graph】

hzoi-liujiahui 2020-11-23 20:25 原文

传送门

思路

这道题从最短路的角度去考虑可能不是很好想,可以考虑从构造的角度,只要确定了起点,那么图的框架就可以顺利成章的构造出来。

最短路可以不考虑,考虑最短路只会使答案复杂化,建出一颗树,路径唯一,就不需要考虑最短路了;其次,有每个点的度数不可以大于k,所以没必要连的边就尽量不连。

考虑度数,除了距离为 0 的节点的边都是连的儿子节点,其他节点在添加父节点时一定有一条边连向了父节点,即只能添加 \(k-1\) 个儿子,而距离为 0 的点就可以连\(k\)个儿子。

首先通过判断距离为x和距离为\(x+1\)的点的个数关系,即(距离为\(x\)的点的个数 \(\times (k - 1)\) > 距离为\(x+1\)的点的个数),距离为 0 的点特殊处理一下,同时判断一下,有可能不存在距离为 0 的点或者存在多个距离为 0 的点都是不合法的,建边就从距离为 \(x\) 的点连向距离为 \(x+1\) 的点就可以。

代码实现 (操作有点累赘)

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 1e6 + 50;
inline int read () {
	int x = 0, f = 1; char ch = getchar();
	for (;!isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
	for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
	return x * f;
}
int n, k;
struct Node {
	int d, id;
} node[maxn];
int cnt[maxn];
vector <int> vec[maxn];
struct Ans {
	int from, to;
} ans[maxn];
bool cmp (Node A, Node B) { return A.d < B.d;}
int Max;
signed main () {
	n = read(), k = read();
	for (int i = 1; i <= n; i++) {
		node[i].d = read();
		node[i].id = i;
		Max = max (node[i].d, Max);
	}
	int cnt = 0;
	sort (node + 1, node + 1 + n, cmp);
	for (int i = 1; i <= n; i++) {
		if (node[i].d == 0) {
			if (cnt != 0) {
				return puts("-1"), 0;
			}
			cnt++;
		}
		vec[node[i].d].push_back(node[i].id);
	}
	for (int i = 1; i < Max; i++) {
		if ((long long)vec[i].size() * (k - 1) < vec[i + 1].size()) return puts("-1"), 0;//记得开long long,不然会爆
	}
	if (cnt == 0) return puts("-1"), 0;
	if (k < vec[1].size()) return puts("-1"), 0;
	int oper = 0, js = 0;
	for (int i = 1; i <= n; i++) {
		if (node[i].d == 0) {
			continue;
		}
		if (node[i].d - node[i - 1].d == 0) {
			if (js == k) {
				js = 1, ++oper;
				ans[i].from = vec[node[i].d - 1][oper], ans[i].to = node[i].id;
			} else if (js == k - 1 && node[i].d != 1) {
				js = 1, ++oper;
				ans[i].from = vec[node[i].d - 1][oper], ans[i].to = node[i].id;
			} else if (js == k - 1 && node[i].d == 1) {
				js ++;
				ans[i].from = vec[node[i].d - 1][oper], ans[i].to = node[i].id;
			}else {
				js++;
				ans[i].from = vec[node[i].d - 1][oper], ans[i].to = node[i].id;
			}
		} else if (node[i].d - node[i - 1].d == 1) {
			oper = 0, js = 1;
			ans[i].from = vec[node[i].d - 1][oper], ans[i].to = node[i].id;
		}
	}
	printf ("%d\n", n - 1);
	for (int i = 2; i <= n; i++) {
		printf ("%d %d\n", ans[i].from, ans[i].to);
	}
	return 0;
}


推荐阅读