一個含有 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 Graphstring