[HNOI2006]公路修建问题 ——二分答案+krukal(蒟弱个人总结)
题意:
题目要求我们在n个景点之间建立n-1条公路,在花费尽量少的情况下至少有k条一级公路,求花费最多的一条公路的最小花费
题解:
- 二分答案+kruskal,在[l,r]之间二分答案,l为输入的最小花费,r为输入的最大花费
- check函数里面跑两次kruskal,第一次选一级公路,第二次选二级公路,如果选的一级公路的条数>=k,并且一级公路数量和二级公路数量==n-1,那么return true,继续二分更小的mid;否则mid太小了,return false
- 不能跑一次kruskal,同时选一级公路和二级公路,因为题目的要求是至少选k条一级公路,如果同时选,可能选不到k条一级公路
AC代码
#include<bits/stdc++.h>
using namespace std;
#define N 10009
#define M 20009
#define mem(a,b) memset(a,b,sizeof a)
int n,m,k,p[M];
int Find(int x)
{
if(x!=p[x]) p[x] = Find(p[x]);
return p[x];
}
struct Edge
{
int a,b,c1,c2;
bool operator <(const Edge &t) const
{
if(t.c1!=c1) return c1<t.c1;
else return c2<t.c2;
}
}edge[M];
bool check(int mid)
{
mem(p, 0);
int cnt1 = 0,res =0,cnt2=0;
for(int i=1; i<=n; i++) p[i] = i;
for(int i=0; i<m-1; i++)
{
int a = Find(edge[i].a),b = Find(edge[i].b);
int c1=edge[i].c1, c2=edge[i].c2;
if(a!=b&&c1<=mid)
{
cnt1++;
p[a] = b;
}
}
if(cnt1<k) return false;
for(int i=0; i<m-1; i++)
{
int a = Find(edge[i].a),b = Find(edge[i].b);
int c1=edge[i].c1, c2=edge[i].c2;
if(a!=b&&c2<=mid)
{
cnt2++;
p[a] = b;
}
}
// cout<<mid<<" ";
//cout<<cnt1+cnt2<<endl;
if(cnt1+cnt2<n-1) return false;
return true;
}
int main()
{
scanf("%d%d%d",&n,&k,&m);
int l=1e9,r=-1;
for(int i=0; i<m-1; i++)
{
int a,b,c1,c2;
scanf("%d%d%d%d",&a,&b,&c1,&c2);
edge[i]={a,b,c1,c2};
l = min(l,min(c1,c2));
r = max(r,max(c1,c2));
}
//排序与否都没关系
// sort(edge,edge+m-1);
while(l<=r)
{
int mid = l+r>>1;
if(check(mid)) r = mid-1;
else l = mid+1;
//puts("wa");
}
cout<<l<<endl;
return 0;
}
蒟弱刷题日记,思路参考洛谷大佬博客
有错误请指出,一起进步呀!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话