Codeforces Round #237 (Div. 2) C. Restore Graph(水构造)

 

题目大意

 

一个含有 n 个顶点的无向图,顶点编号为 1~n。给出一个距离数组:d[i] 表示顶点 i 距离图中某个定点的最短距离。这个图有个限制:每一个点的度不能超过 kios

如今,请构造一个这样的无向图,要求不能有自环,重边,且知足距离数组和度数限制,输出图中的边;若是无解,输出 -1数组

 

数据规模:1 ≤ k <  n ≤ 105,0 ≤ d[i] < n
ide

 

作法分析

 

第一眼作法:SPFA 或者 BFS,想了想,仍是乱搞优化

根据 d 数组直接构造这个图,由于最短路具备最优子结构,因此,d[i] 为 0 的点只有一个,从 0 到 maxLen 的全部距离,都必定在 d 数组中出现过,而后就考虑度数限制。spa

显然,距离为 len + 1 的点是由距离为 len 的点到达的,因而,将全部的点按照距离分类。要尽可能知足度数限制,每一个点的度数就要尽可能少,因此,距离相同的点之间不能有边。因而,构造出来的解中,全部的边 (u, v) 必定知足这样的性质:d[u] == d[v] + 1(假设 d[u] > d[v]),这让我想起了 ISAP 求最大流的 gap 优化code

而后,怎么保证每一个点都尽可能知足度数限制呢?平均分配blog

将距离为 len + 1 的点平均分配到距离为 len 的点里面去,这样必定是最优的,若是这样都不知足度数限制,确定无解了get

 

参考代码

 

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <algorithm>
 6 
 7 using namespace std;
 8 
 9 const int N = 100005;
10 
11 int k, n, d[N];
12 vector <int> len[N];
13 vector < pair <int, int> > edge;
14 
15 int main() {
16     scanf("%d%d", &n, &k);
17     for (int i = 0; i <= n; i ++) len[i].clear();
18     for (int i = 1; i <= n; i ++) {
19         scanf("%d", &d[i]);
20         len[d[i]].push_back(i);
21     }
22     if (len[0].size() != 1) {
23         printf("-1\n");
24         return 0;
25     }
26     int maxLen = n;
27     for (; len[maxLen].size() == 0; maxLen --);
28     for (int i = 0; i <= maxLen; i ++) {
29         if (len[i].size() == 0) {
30             printf("-1\n");
31             return 0;
32         }
33     }
34     edge.clear();
35     for (int i = 1; i <= maxLen; i ++) {
36         int cnt1 = (int)len[i - 1].size();
37         int cnt2 = (int)len[i].size();
38         int cnt = cnt2 / cnt1 + (cnt2 % cnt1 != 0);
39         if (cnt + (i - 1 != 0) > k) {
40             printf("-1\n");
41             return 0;
42         }
43         for (int id1 = 0, id2 = 0; id1 < cnt1 && id2 < cnt2; id1 ++) {
44             for (; id2 < (id1 + 1) * cnt && id2 < cnt2; id2 ++) {
45                 edge.push_back(make_pair(len[i - 1][id1], len[i][id2]));
46             }
47         }
48     }
49     int cnt = (int)edge.size();
50     printf("%d\n", cnt);
51     for (int i = 0; i < cnt; i ++) {
52         printf("%d %d\n", edge[i].first, edge[i].second);
53     }
54     return 0;
55 }
C. Restore Graph

 

题目连接

 

C. Restore Graphstring

相关文章
相关标签/搜索