旅行计划 - Travel Plan - Kruskal
旅行计划
(测试用例总数:X个,1.5秒(C/C++),2秒(JAVA)/内存限制:256 M,Stack 1 M)
琳恩正在计划前往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
思路分析:
通过利用最少的道路来访问N座城市,而每座城市至少需要访问一次 ,由此可推断出是求最小生成树,可使用Kruskal。
她必须要返回出发城市才能结束此次旅行,即距离=最小生成树的距离*2
K次旅行,说明是K个连通分量,说明只需要循环N-K次
package graph;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;
/**
* 思路分析:
* 通过利用最少的道路来访问N座城市,而每座城市至少需要访问一次 ,由此可推断出是求最小生成树,可使用Kruskal。
* 她必须要返回出发城市才能结束此次旅行,即距离=最小生成树的距离*2
* K次旅行,说明是K个连通分量,说明只需要循环N-K次
*
* @author XA-GDD
*
*/
public class TravelPlan_0720 {
static int T,N,M,K;
static int _Max_N = 100000;
static int _Max_M = 200000;
static TravelPlanNode [] srcArr = new TravelPlanNode[_Max_M];
static int [] parent = new int[_Max_N+1];
static int count;
static long ans;
public static void main(String[] args) throws IOException {
System.setIn(new FileInputStream("D:\\workspace\\eclipse-workspace\\sw_pro\\test_case\\sample_input_0720.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
T = Integer.parseInt(st.nextToken());
for(int testCase = 1; testCase<=T;testCase++) {
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
init();
for(int i=0;i<M;i++) {
st = new StringTokenizer(br.readLine());
srcArr[i] = new TravelPlanNode(Integer.parseInt(st.nextToken()),Integer.parseInt(st.nextToken()),Integer.parseInt(st.nextToken()));
}
//根据权值排序
Arrays.sort(srcArr,0,M,new comTravelPlan());
for(int i=0;i<M;i++) {
if(count==N-K) {
break;
}
if(find(srcArr[i].start)!=find(srcArr[i].end)) {
union(srcArr[i].start,srcArr[i].end);
count++;
ans += (long)srcArr[i].cost*2;
}
}
System.out.println("#"+testCase+" "+ans);
}
}
static void init() {
Arrays.fill(srcArr, null);
for(int i=0;i<N;i++) {
parent[i]=i;
}
ans=0L;
count=0;
}
static int find(int n) {
if(parent[n]==n) return n;
return parent[n] = find(parent[n]);
}
static void union(int a, int b) {
int pa = find(a);
int pb = find(b);
if(pa==pb) return;
if(pa>pb) {
parent[pb]=pa;
}else {
parent[pa]=pb;
}
}
}
class TravelPlanNode{
int start;
int end;
int cost;
TravelPlanNode(int start, int end ,int cost){
this.start=start;
this.end=end;
this.cost=cost;
}
}
class comTravelPlan implements Comparator<TravelPlanNode>{
@Override
public int compare(TravelPlanNode o1, TravelPlanNode o2) {
return o1.cost-o2.cost;
}
}
浙公网安备 33010602011771号