2022河南萌新联赛第(五)场:B.交通改造(并查集)
https://ac.nowcoder.com/acm/contest/38718/B
题目描述
A城是一座繁忙又有活力的城市,随着城市的发展,原有的道路越发拥堵,所以政府决定对原有的道路交通系统进行改造。
A城目前的道路是这样的:城市中有n个交叉路口,部分交叉路口通过道路直接相连,任意两个交叉路口之间最多有一条道路连接。A城的只有双向道,没有单向道,并且所有交叉路口都通过道路直接或间接相连。现在给每条道路设定一个通畅值,通畅值越小则该道路越繁忙也越需要改造。出于节约资金的思想考虑,现在政府希望改造的道路尽可能少,于是提出了下列要求:接受改造的道路能够令所有的交叉路口直接或间接相连,并且改造的道路数量应尽可能的少,其次在满足上述条件的情况下,令被改造的道路中通畅值最大的道路的通畅值尽量小。
现在你作为政府的顾问,请设计一套方案,确定哪些道路需要被改造。
输入描述:
第一行有两个整数n,m表示城市有n个交叉路口,m条道路。
接下来m行是对每条道路的描述,u, v,c表示交叉路口u和v之间有道路相连,分值为c。
输出描述:
两个整数s,max,表示你选出了几条道路,分值最大的那条道路的分值是多少。
示例1
输入
4 5
1 2 3
1 4 5
2 4 7
2 3 6
3 4 8
复制
3 6
-
题目意思简化版:给定n个点,m条双向边,每条双向边带一个权值。权值越小,越需要改造,权值越大,越不需要。
-
要求是:接受改造的道路能够和所有的交叉路口直接或间接相连,这就说明了所有的节点都必须连一个集合里面;
-
并且改造的道路数量应尽可能的少,能最小化连接成集合的数量,连完就跑路。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=200200,M=2002;
int father[N];
struct node
{
int x;
int y;
int z;
}a[N];
bool cmp(node l,node r)
{
return l.z<r.z;
}
int find(int x)
{
if(father[x]!=x) father[x]=find(father[x]);
return father[x];
}
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
LL T=1;
//cin>>T;
while(T--)
{
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>a[i].x>>a[i].y>>a[i].z;
}
//通畅值越小则该道路越繁忙也越需要改造
sort(a+1,a+1+m,cmp);
for(int i=1;i<=n;i++)
father[i]=i;
int flag=0,ans=0;
for(int i=1;i<=m;i++)
{
//接受改造的道路能够令所有的交叉路口直接或间接相连
int fa=find(a[i].x),fb=find(a[i].y);
//所以一旦发现有需要粘在一起的,就得黏在一起
//不然的话就换下一个
if(fa!=fb)
{
flag++;
father[fa]=fb;
if(flag==n-1)
{
ans=a[i].z;
break;
}
}
}
cout<<n-1<<" "<<ans<<endl;//n个点需要构成一棵树,肯定是需要连接n-1条边的
}
return 0;
}