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

相關文章
相關標籤/搜索