题目
琳恩正在计划前往S国进行K次旅行。
S国有N座城市,城市之间通过M条道路连接着。琳恩可从任意一座城市前往另一座城市,移动时,每条道路均会产生通行费,所以她需要支付费用。
琳恩计划在K次旅行期间,通过利用最少的道路来访问N座城市,而每座城市至少需要访问一次。如果按照如上的方式旅行时,存在多种方案的话,琳恩想找出其中花费最低的出行方案作为旅行计划。
琳恩可以选择K次旅行时的出发城市,但她必须要返回出发城市才能结束此次旅行。请帮助琳恩求出旅行时所需要的最低费用。
如上图所示,假设分成两次来旅行六座城市,第一次旅行是从城市①出发,沿着 ①→②→③→②→① 的路径旅行,这时她利用了两条道路旅行了三座城市,最终花费了8。(再次途经同一条道路时,虽然利用的道路次数不会增加,但需要再次支付通行费)。如果沿着 ①→②→③→① 的路径旅行时,虽然产生的费用会更低,花费是7,但她不会采取该路线,因为该路线需要经过更多的道路。第二次旅行是从城市⑥出发,沿着⑥→④→⑥→⑤→⑥旅行,这时她仅利用了两条道路旅行了三座城市,花费为18。按照以上计划,通过两次旅行,她只需利用四条道路便可旅行所有的六座城市,花费为26。这是琳恩想要的最佳旅行方案之一。
[限制条件]
1.城市数量N为介于3到100,000之间的整数。
2.道路数量M为介于N-1到200,000之间的整数。
3.旅行次数K为介于2到N之间的整数。
4.道路通行费C为介于1到100,000之间的整数。
5.再次途径相同道路时,仍然需要支付通行费。
[输入]
首先给出测试用例数量T,接着给出T种测试用例。每个测试用例的第一行空格区分给出城市数N、道路数M以及旅行次数K。第二行开始,通过M行,每行按照A B C(城市A,城市B,通行费C)的格式空格区分给出道路信息。
[输出]
每个测试用例输出一行。首先输出“#x”(x为测试用例编号,从1开始),加一个空格,输出K 次旅行所需要的最低费用。
[输入输出 示例]
(输入)
2
6 10 2
1 2 2
1 3 3
1 5 5
2 4 6
2 3 2
3 4 5
3 6 5
3 5 5
4 6 5
5 6 4
6 10 3
1 2 2
1 3 3
1 5 5
2 4 6
2 3 2
3 4 5
3 6 5
3 5 5
4 6 5
5 6 4
(输出)
#1 26
#2 16
思路
克鲁斯卡尔求出原图的最小生成树,然后每去掉一条边(要使用的边的权值之和最小,则需要去掉最小生成树中权值最大的边),就会被多分出来一个连通分量。
代码(调整前):
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static int T, N, M, K, MST_EDGE_COUNT;
static long ASW;
static ArrayList<Edge> DATA;
static ArrayList<Long> MST;
static int[] UF;
static class Edge {
int from, to, cost;
public Edge(int s, int e, int c) {
this.from = s;
this.to = e;
this.cost = c;
}
}
public static void main(String[] args) throws IOException {
System.setIn(new FileInputStream("D:\\SW\\TestCase\\sample_input_20210720.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int T = Integer.parseInt(st.nextToken()); // Case数量
for (int t = 1; t <= T; t++) {
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken())