• 题解 CF404C 【Restore Graph】


    传送门

    思路

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

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

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

    首先通过判断距离为x和距离为(x+1)的点的个数关系,即(距离为(x)的点的个数 ( imes (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 - 1);
    	for (int i = 2; i <= n; i++) {
    		printf ("%d %d
    ", ans[i].from, ans[i].to);
    	}
    	return 0;
    }
    
    
    
  • 相关阅读:
    POJ 3279 Fliptile 枚举+搜索
    POJ 3278 Catch That Cow
    CS Academy Round41 BFS+DFS
    CS Academy Round41 Tennis Tournament
    CS Academy Round41 Cinema Seats
    POJ 1177 Picture
    HDU 1255 覆盖的面积
    POJ 1151 Atlantis 线段树+离散化
    HDU 4614 Vases and Flowers 线段树+二分
    凑数问题
  • 原文地址:https://www.cnblogs.com/hzoi-liujiahui/p/14026807.html
Copyright © 2020-2023  润新知