问题描述
试题编号: | 201703-4 |
试题名称: | 地铁修建 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 A市有n个交通枢纽,其中1号和n号非常重要,为了加强运输能力,A市决定在1号到n号枢纽间修建一条地铁。 输入格式 输入的第一行包含两个整数n, m,用一个空格分隔,分别表示交通枢纽的数量和候选隧道的数量。 输出格式 输出一个整数,修建整条地铁线路最少需要的天数。 样例输入 6 6 样例输出 6 样例说明 可以修建的线路有两种。 评测用例规模与约定 对于20%的评测用例,1 ≤ n ≤ 10,1 ≤ m ≤ 20; |
本题是求一条从1到n的通路,同时这个通路上的最大权值最小。用最小生成树来做,同时本题是要找边,所以用克鲁斯卡尔算法。遍历每条边,判断这条边加入边集中是否会形成环路,用并查集来实现。若1和n已经连通了,则退出遍历,因为权值已经从小到大排序了,所以最后一条遍历到的边就是结果。代码如下:
#include<iostream>
#include<algorithm>
#define max 2000001
using namespace std;
//边的结构体
struct gra
{
int s;
int e;
int v;
}edge[max];
//储存每个点的源点
int parent[max];
int n,m;
//将数组按权值从小到大排序
bool cmp(struct gra n1,struct gra n2)
{
return n1.v<n2.v;
}
//找源点
int find(int a)
{
int temp=a;
while(a!=parent[a])
a=parent[a];
//路径压缩
while(temp!=parent[temp])
{
int b=parent[temp];
parent[temp]=a;
temp=b;
}
return a;
}
int kruscal(int m)
{
int res=0;
//遍历每条边
for(int i=1;i<=m;i++)
{
//找到起点和终点的源点
int a=find(edge[i].s);
int b=find(edge[i].e);
res=edge[i].v;
//若这条边加入边集后会形成环路,则放弃这条边,选择次小边。否则将这条边加入边集
if(a!=b)
parent[b]=a;
//如果已经将整个图连通起来了则退出循环
if(find(1)==find(n))
break;
}
return res;
}
int main()
{
int cost;
cin>>n>>m;
for(int i=1;i<=m;i++)
cin>>edge[i].s>>edge[i].e>>edge[i].v;
sort(edge+1,edge+m+1,cmp);
for(int i=1;i<=n;i++)
parent[i]=i;
cout<<kruscal(m);
return 0;
}