洛谷P2323 [HNOI2006] 公路修建问题

news/2024/10/8 22:02:28

Problem

给出n个点、m条边的无向连通图,每条边具有2个边权,一高一低,我们需要选择若干条边,使得图连通的情况下选择至少k条较高边权,输出选择的边中,边权最大值的最小值,输出答案的一半(保证偶数)

Slove

假设每条边只具有1条边权,答案显而易见,跑一遍最小生成树即可,因为最小生成树就是最小瓶颈树
但是如果存在较高边权且需要选至少k个,该怎么办呢?
注意到,Kruskal算法的本质就是贪心,每次选择最小的边,如果二点未连通,则用并查集合并,否则跳过,直到选择n-1条边
所以此时我们可以将所有边权都遍历一遍,当选择较高边权时k-1,如果k=还需要选择的边时,跳过所有较低边权......吗?
不难发现,此时最小生成树=最小瓶颈树不再适用,但我们可以按照这种贪心思路,优先选择k条较高边权,然后再根据需要选择剩下的边权(也包括较高边权,因为有时某一条边的较低边权可能比另一条边的较高边权还要高!)。因为k条高级边始终是要选择的,且高于低级边权。
时间复杂度就是Kruskal的时间复杂度,为\(O(nlogn)\)

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#include<cstdlib>
#include<list>
#include<map>
#include<queue>
#include<stack>
#include<vector>
using namespace std;
int n,k,m,ans;
int f[10005];
struct p{int st,to,w,idx;bool type;
};
vector<p> g,road;
bool cmp(p a,p b){if(a.w!=b.w)return a.w<b.w;return a.type>b.type;
}
bool cmp1(p a,p b){return a.idx<b.idx;
}
int find(int u){if(f[u]==u)return u;return f[u]=find(f[u]);
}
bool same(int u,int v){return find(u)==find(v);
}
bool unit(int u,int v){if(same(u,v))return false;f[find(u)]=v;return true;
}
void kruskal(){int edge=n-1;for(int i=0;i<g.size();i++){if(k>0&&!g[i].type){continue;}if(k==0){i=0;k--;}if(unit(g[i].st,g[i].to)){k-=g[i].type;edge--;ans=max(ans,g[i].w);road.push_back(g[i]);}if(!edge)break;}
}
int main(){cin>>n>>k>>m;for(int i=1;i<=n;i++)f[i]=i;for(int i=1,st,to,w1,w2;i<m;i++){cin>>st>>to>>w1>>w2;g.push_back({st,to,w1,i,1});g.push_back({st,to,w2,i,0});}sort(g.begin(),g.end(),cmp);kruskal();cout<<ans<<endl;sort(road.begin(),road.end(),cmp1);for(int i=0;i<road.size();i++){int type;if(road[i].type==1)type=1;else type=2;cout<<road[i].idx<<" "<<type<<endl;}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/69174.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

Android开发:日志功能备忘

临时记一下吧,以后就直接复制粘贴这里面的好了。实现一个日志记录程序的运行状态,并且带上时间信息,可以写一个类灵活调用。 MyLog.java package com.example.networkaccessrestrictions;import static android.content.ContentValues.TAG;import android.content.Context; …

学年(2024-2025-3) 学号(20241424)《计算机基础与程序设计》第三周学习总结

学期(2024-2025-3) 学号(20241424) 《计算机基础与程序设计》第三周学习总结 作业信息 |这个作业属于([2024-2025-3-计算机基础与程序设计](https://www.cnblogs.com/rocedu/p/9577842.html#WEEK03)| |-- |-- | |这个作业要求在(2024-2025-3计算机基础与程序设计第三周作…

mysql join语法解析

MySQL 支持以下 JOIN 语法用于 SELECT 语句和多表 DELETE 和 UPDATE 语句中的 table_references 部分: table_references: 查询中涉及的一个或多个表的引用,可以是简单表名或 JOIN 表达式的组合。 escaped_table_reference [, escaped_table_reference] ...escaped_table_ref…

Tableau修改行和列的颜色

1.修改颜色 1.1 在列上右键点击设置格式1.2 修改列和角2.逆时针、由里及外依次设置格式在直条上右键

论文《Learning Properties of Ordered and Disordered Materials from Multi-fidelity Data》中的代码实现

github地址:https://github.com/materialsvirtuallab/megnet/tree/master/multifidelity#issues介绍:当前的存储库利用了由同一作者开发的现有MEGNET软件包,并将MEGNET功能扩展到多保真数据集的建模。该存储库将共享公开发布的多保真带隙数据,并展示了运行多保真数据集的模…

Tableau双轴

1.添加度量到行2.添加分类到列3.拖动度量到左侧利润字段处放开

Tableau文本表、直条、散点图、折线图、

1文本表 两次双击选中两个维度2.直条 两次双击依次分别选中一个度量和维度3.散点图 两次双击选中两个度量4.折线图 两次双击依次分别选中一个日期和一个度量