#P14938. [uoi2019]道路建设

    ID: 14154 传统题 2000ms 512MiB 尝试: 1 已通过: 1 难度: 6 上传者: 标签>CF2000最小生成树并查集贪心图论构造排序

[uoi2019]道路建设

题目描述

哥萨克·乌斯终于找到了自己梦想中的国家。这个国家有 nn 座城市,城市之间一开始没有任何道路。乌斯想改变这种情况,于是设计了 mm 条可以修建的无向道路。每条道路连接两座不同的城市。

问题在于:每座城市 ii 最多能拿出 cic_i 个硬币用于修路,而第 jj 条道路的修建费用为 wjw_j 个硬币。因此,乌斯决定只修建若干条道路,只要最终所有城市连通即可。

在规划时,乌斯意识到:随着道路逐条修建,城市会合并成若干连通块。若要修建第 jj 条道路,则这条道路两端所在连通块的总预算必须至少为 wjw_j,因为必须先支付费用,之后道路才能建成。道路建成后,两个连通块的预算合并,并扣除这条道路的费用。

已知每座城市的预算 cic_i,以及每条候选道路的两个端点 vi,uiv_i,u_i 和费用 wiw_i。请判断是否可以选择若干条道路并安排修建顺序,使得最后所有城市连通;如果可以,请输出一种修建顺序。

函数提交说明

原题提供如下函数用于报告要修建的道路:

void add(int i);

调用该函数表示修建编号为 ii 的道路。

你需要实现:

bool solve(int n, int m, int g,
           vector<int> c,
           vector<int> v,
           vector<int> u,
           vector<int> w);

参数含义如下:

  • nn:城市数;
  • mm:候选道路数;
  • gg:测试块编号;
  • cic_i:第 ii 座城市的初始预算;
  • vi,uiv_i,u_i:第 ii 条道路连接的两个城市;
  • wiw_i:修建第 ii 条道路需要的硬币数。

该函数应在可行时返回 true,不可行时返回 false。若返回 true,则在返回前必须按照实际修建顺序调用 add 输出所有修建道路。

输入格式

第一行包含三个整数 n,m,gn,m,g1n1061\le n\le10^60m1060\le m\le10^60g70\le g\le7),分别表示城市数、道路数和测试块编号。

第二行包含 nn 个整数 c1,c2,,cnc_1,c_2,\ldots,c_n1ci1061\le c_i\le10^6),表示每座城市的初始预算。

接下来 mm 行,每行包含三个整数 vi,ui,wiv_i,u_i,w_i1vi,uin1\le v_i,u_i\le n1wi1061\le w_i\le10^6),表示第 ii 条道路的端点和修建费用。

输出格式

若不可行,第一行输出 -1

否则第一行输出 qq,表示修建道路条数;随后 qq 行每行输出一个整数 xx,表示修建的道路编号。

样例 1

4 5 0
2 5 2 4
1 2 7
3 4 4
1 4 5
4 2 3
3 2 4
3
4
2
3

样例 2

3 3 0
6 2 5
2 3 9
2 1 5
1 3 10
-1

样例说明

样例一中,先修建编号为 44 的道路,城市 2244 合并,并从其总预算中支付 33 个硬币,合并块剩余 66 个硬币。再修建编号为 22 的道路后,该连通块预算变为 44。最后修建第 33 条道路,所有城市连通且预算足够支付费用。

样例二中,不存在一种道路选择和修建顺序能够让所有城市连通且支付所有费用。

计分方式

编号 限制 分数
1 n10n\le10m=n1m=n-1ci=1c_i=1wi=1w_i=1,若建完全部 mm 条道路则所有城市连通 3
2 n,m10n,m\le10 8
3 n,m105n,m\le10^5ci=1c_i=1 12
4 n,m105n,m\le10^5,所有 wiw_i 相同 14
5 n,m103n,m\le10^3 16
6 n,m105n,m\le10^5 19
7 n,m5105n,m\le5\cdot10^5 12
8 无额外限制 16