测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

A28834. 繁忙的都市(city)

填空题 困难

题目描述

繁忙的都市(city)

题目描述

城市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; #define N 305 struct Edge { int v, w; Edge(){} Edge(int a, int b):v(a),w(b){}; }; vector<Edge> edge[N]; bool vis[N]; int n, m, mx, dis[N]; void prim() { memset(dis, 0x3f, sizeof(dis)); dis[1] = 0; for(int k = 1; k <= n; ++k) { int u = 0; for(int i = 1; i <= n; ++i) if(vis[i] == false && (u == 0 || dis[i] < dis[u])) u = i; vis[u] = true; mx = max(mx, dis[u]); for(Edge e : edge[u]) { int v = e.v, w = e.w; if(vis[v] == false && dis[v] > w) dis[v] = w; } } } int main() { int f, t, w; cin >> n >> m; for(int i = 1; i <= m; ++i) { cin >> f >> t >> w; edge[f].push_back(Edge(t, w)); edge[t].push_back(Edge(f, w)); } prim(); cout << n-1 << ' ' << mx; return 0; }

答案解析

将题目叙述转为图论概念,交叉路口为顶点,道路为边,道路是双向的,且所有交叉路口都直接或间接连接起来,说明这是无向连通图。每条道路的分值,就是边的权值。政府要改造一些道路,就是选一些边。

三个要求的概念分别为:


选择的边构成的图应该是连通图,且应该包含原图所有顶点。

选择的边尽可能少。

边最少时,该图就成了无根树。边数为顶点数减1。

综合以上两点,选择的边及顶点构成的图就是原图的生成树。

生成树有多种方案,选择其中权值最大的边最小的那一种生成树方案,即瓶颈生成树。

树上最大边权值在图的所有生成树中最小的生成树,叫做瓶颈生成树。

最小生成树一定是瓶颈生成树,但瓶颈生成树未必是最小生成树。(其证明见百度百科)


题目要求的就是瓶颈生成树,我们可以直接求出最小生成树,它一定是瓶颈生成树。

该题顶点数<=300,边数<=100000,使用Prim,Prim堆优化,Kruskal都可以完成该题。

上一题 下一题