題解 CF404C 【Restore Graph】
阿新 • • 發佈:2020-11-23
思路
這道題從最短路的角度去考慮可能不是很好想,可以考慮從構造的角度,只要確定了起點,那麼圖的框架就可以順利成章的構造出來。
最短路可以不考慮,考慮最短路只會使答案複雜化,建出一顆樹,路徑唯一,就不需要考慮最短路了;其次,有每個點的度數不可以大於k,所以沒必要連的邊就儘量不連。
考慮度數,除了距離為 0 的節點的邊都是連的兒子節點,其他節點在新增父節點時一定有一條邊連向了父節點,即只能新增 \(k-1\) 個兒子,而距離為 0 的點就可以連\(k\)個兒子。
首先通過判斷距離為x和距離為\(x+1\)的點的個數關係,即(距離為\(x\)的點的個數 \(\times (k - 1)\) > 距離為\(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; }