b_lg_繁忙的都市(二分边权 / 最小生成树)
城市中每条道路都有一个分值,分值越小表示这个道路越繁忙,越需要进行改造。
但是市政府的资金有限,市长希望进行改造的道路越少越好,于是他提出下面的要求:
1.改造的那些道路能够把所有的交叉路口直接或间接的连通起来。
2.在满足要求1的情况下,改造的道路尽量少。
3.在满足要求1、2的情况下,改造的那些道路中分值最大的道路分值尽量小。
输出:选出了几条道路,分值最大的那条道路的分值是多少。
方法一:二分最大边权
叫你去掉几条边权较大的边,使得总边权最小,且保持图仍然连通(最小生成树的题),可以用二分枚举一个边权,判断用当前边权下能否遍历完剩下的结点(相当于去掉了一些边)
#include<bits/stdc++.h>
using namespace std;
const int N=305;
struct node {
int u,w;
};
vector<node> g[N];
int n,m,st[N];
void dfs(int u, int maxw) {
st[u]=1;
for (auto& to : g[u]) {
int v=to.u, w=to.w;
if (st[v] || w>maxw) continue;
dfs(v,maxw);
}
}
bool vis_all(int w) {
memset(st,false,sizeof st);
dfs(1,w);
for (int i=1; i<=n; i++) if (!st[i])
return false;
return true;
}
int main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin>>n>>m;
for (int i=0; i<m; i++) {
int u,v,w; cin>>u>>v>>w;
g[u].push_back({v,w});
g[v].push_back({u,w});
}
int l=1, r=1e5+5;
while (l<r) {
int w=l+r>>1;
if (vis_all(w)) r=w;
else l=w+1;
}
cout<<n-1<<' '<<l<<'\n';
return 0;
}