题目描述
城市 C 是一个非常繁忙的大都市,城市中的道路十分的拥挤,于是市长决定对其中的道路进行改造。城市 C 的道路是这样分布的:城市中有 n 个交叉路口,有些交叉路口之间有道路相连,两个交叉路口之间最多有一条道路相连接。这些道路是双向的,且把所有的交叉路口直接或间接的连接起来了。每条道路都有一个分值,分值越小表示这个道路越繁忙,越需要进行改造。但是市政府的资金有限,市长希望进行改造的道路越少越好,于是他提出下面的要求:
1.改造的那些道路能够把所有的交叉路口直接或间接的连通起来。
2.在满足要求 1 的情况下,改造的道路尽量少。
3.在满足要求 1、2 的情况下,改造的那些道路中分值最大值尽量小。
作为市规划局的你,应当作出最佳的决策,选择那些道路应当被修建。
输入描述
第一行有两个整数 n,m 表示城市有 n 个交叉路口,m 条道路。接下来 m 行是对每条道路的描述,u, v, c 表示交叉路口 u 和 v 之间有道路相连,分值为 c。(1≤n≤300,1≤c≤10000)。
输出描述
两个整数 s, max,表示你选出了几条道路,分值最大的那条道路的分值是多少。
样例输入
4 5 1 2 3 1 4 5 2 4 7 2 3 6 3 4 8
样例输出
3 6
一道最小生成树的题目
这里就直接把最短网络的代码复制过来了
#include<bits/stdc++.h>
using namespace std;
const int N=2e5;
int cnt;
struct node{
int u,v,w;
}a[N];
int f[N];
int n;
int find(int x){
if(f[x]!=x)f[x]=find(f[x]);
return f[x];
}
bool cmp(node a,node b){
return a.w<b.w;
}
int kru(){
sort(a+1,a+1+cnt,cmp);
for(int i=1;i<=cnt;i++)f[i]=i;
int sum=0;
for(int i=1;i<=cnt;i++){
int u=a[i].u;
int v=a[i].v;
int w=a[i].w;
if(find(u)==find(v))continue;
else{
f[find(u)]=find(v);
sum+=w;
}
}
return sum;
}
signed main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int x;
scanf("%d",&x);
a[++cnt]=node{i,j,x};
}
}
printf("%d",kru());
}
然后,中间得改一下,首先,学过图论的都知道,使一个图联通所需的最少边数是点数减一,这里就直接输出了
接着就是最大边长度,我们要先在里面加一个特判就是如果选择的边数到了需要的n-1条边,就直接跳出循环,因为如果再找,可能会把后面更大的边(因为是排过序的)加进去,答案就不对了
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e7+5;
int n,m;
struct node{
int u,v,w;
}a[N];
int f[N+N];
int find(int x){
if(f[x]!=x)f[x]=find(f[x]);
return f[x];
}
bool cmp(node x,node y){
return x.w<y.w;
}
int sum=0;
void kru(){
sort(a+1,a+1+m,cmp);
for(int i=1;i<=n;i++)f[i]=i;
int s=0;
for(int i=1;i<=m;i++){
if(s==n-1)break;
int u=a[i].u;
int v=a[i].v;
int w=a[i].w;
if(find(u)==find(v))continue;
else{
int fu=find(u),fv=find(v);
if(fu!=fv)f[fu]=fv;
sum=w;
s++;
}
}
}
signed main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%lld%lld%lld",&u,&v,&w);
a[i]=node{u,v,w};
}
kru();
printf("%lld %lld",n-1,sum);
}