[BZOJ4883][Lydsy1705月赛]棋盘上的守卫[最小基环树森林]
题意
有一大小为 \(n*m\) 的棋盘,要在一些位置放置一些守卫,每个守卫只能保护当前行列之一,同时在每个格子放置守卫有一个代价 \(w\) ,问要使得所有格子都能够被保护,需要最少多少的代价。
\(2\leq n,m\leq 10^5\ ,n*m\leq 10^5\)
分析
将行列看成 \(n+m\) 个点。将每个格点放置守卫看成所在行列连了一条边,然后把每条边定向,如果被指向表示当前格点对当前 行/列 进行了保护。
这样就会有 \(n+m\) 个点,\(n+m\) 条有向边,同时每条边最多有 1 的入度。形成了基环树森林。
最小基环树森林可以通过 \(Kruskal\) 贪心求解,证明仍然可以考虑反证法。
总时间复杂度为 \(O(n)\) 。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=2e5 + 7;
int n,m,edc;
int par[N],c[N];
struct edge{
int last,to,dis;
edge(){}edge(int last,int to,int dis):last(last),to(to),dis(dis){}
bool operator <(const edge &rhs)const{
return dis<rhs.dis;
}
}e[N*2];
int getpar(int a){return par[a]==a?a:par[a]=getpar(par[a]);}
LL Kruskal(){
sort(e+1,e+1+edc);int cnt=0;LL res=0;
for(int i=0;i<N;i++) par[i]=i;
for(int i=1;i<=edc;i++){
int x=getpar(e[i].last),y=getpar(e[i].to);0
if(x==y&&!c[x]) c[x]=1,cnt++,res+=e[i].dis;
if(x!=y&&!(c[x]&&c[y])) par[x]=y,c[y]|=c[x],cnt++,res+=e[i].dis;
if(cnt==n+m) return res;
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1,x;j<=m;j++){
scanf("%d",&x);
e[++edc]=edge(i,j+n,x);
}
printf("%lld\n",Kruskal());
return 0;
}
[BZOJ4883][Lydsy1705月赛]棋盘上的守卫[最小基环树森林]的更多相关文章
- 【题解】BZOJ4883: [Lydsy1705月赛]棋盘上的守卫(最小生成基环森林)
[题解]BZOJ4883: [Lydsy1705月赛]棋盘上的守卫(最小生成基环森林) 神题 我的想法是,每行每列都要有匹配且一个点只能匹配一个,于是就把格点和每行每列建点出来做一个最小生成树,但是不 ...
- bzoj4883 [Lydsy1705月赛]棋盘上的守卫 最小生成基环树森林
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4883 题解 每一行和每一列都必须要被覆盖. 考虑对于每一行和每一列都建立一个点,一行和一列之间 ...
- 【bzoj4883】[Lydsy2017年5月月赛]棋盘上的守卫 最小环套树森林
题目描述 在一个n*m的棋盘上要放置若干个守卫.对于n行来说,每行必须恰好放置一个横向守卫:同理对于m列来说,每列必须恰好放置一个纵向守卫.每个位置放置守卫的代价是不一样的,且每个位置最多只能放置一个 ...
- BZOJ4883: [Lydsy1705月赛]棋盘上的守卫(最小环套树森林&优化定向问题)
4883: [Lydsy1705月赛]棋盘上的守卫 Time Limit: 3 Sec Memory Limit: 256 MBSubmit: 475 Solved: 259[Submit][St ...
- [BZOJ4883][Lydsy1705月赛]棋盘上的守卫(Kruskal)
对每行每列分别建一个点,问题转为选n+m条边,并给每条边选一个点覆盖,使每个点都被覆盖.也就是最小生成环套树森林. 用和Kruskal一样的方法,将边从小到大排序,若一条边被选入后连通块仍然是一个环套 ...
- BZOJ 4883: [Lydsy1705月赛]棋盘上的守卫 最小生成树 + 建模
Description 在一个n*m的棋盘上要放置若干个守卫.对于n行来说,每行必须恰好放置一个横向守卫:同理对于m列来说,每列 必须恰好放置一个纵向守卫.每个位置放置守卫的代价是不一样的,且每个位置 ...
- [CF1027F]Session in BSU[最小基环树森林]
题意 有 \(n\) 门课程,每门课程可以选择在 \(a_i\) 或者 \(b_i\) 天参加考试,每天最多考一门,问最早什么时候考完所有课程. \(n\leq 10^6\). 分析 类似 [BZOJ ...
- 【BZOJ4883】 [Lydsy1705月赛]棋盘上的守卫(最小生成树,基环树)
传送门 BZOJ Solution 考虑一下如果把行,列当成点,那么显然这个东西就是一个基环树对吧. 直接按照\(Kruscal\)那样子搞就好了. 代码实现 代码戳这里
- BZOJ4886: [Lydsy1705月赛]叠塔游戏(环套树森林&贪心)
4886: [Lydsy1705月赛]叠塔游戏 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 198 Solved: 76[Submit][Stat ...
随机推荐
- [C++] 用Xcode来写C++程序[1] 新建C++项目工程
用Xcode来写C++程序[1] 新建C++项目工程 第一节从新建工程并编译C++源码开始 新建工程 源码: // // main.cpp // YeHelloWorld // // Created ...
- September 17th 2017 Week 38th Sunday
Distance could make you forget about them, but the memories would always be there. 距离会让你遗忘,但是回忆却始终在那 ...
- * args 和 **kwargs
def func(*args, **kwargs): print(args,kwargs) func("对", "哦",o=4, k=0) 结果---> ...
- SDN2017 第一次实验作业
1. 安装mininet 从github上获取Mininet源码并运行安装脚本 $ git clone git://github.com/mininet/mininet $ ./mininet/uti ...
- APP分析之海豚睡眠
APP分析之海豚睡眠 产品:海豚睡眠 引文 由于笔者暑假经常晚睡,导致在习惯性失眠.长时间睡眠不足,导致头脑反应迟钝,还整日无精打采,不知所措.一个偶然的机会,在一个燥热的夜晚,眼看又是一个不眠之夜, ...
- css背景精华所在+前端页面开发流程
background属性 background属性是css中应用比较多,且比较重要的一个属性,它是负责给盒子设置背景图片和背景颜色的,background是一个复合属性,它可以分解成如下几个设置项: ...
- php实现动态随机验证码机制(CAPTCHA)
php实现动态随机验证码机制 验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Ap ...
- 51 nod 1682 中位数计数
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1682 1682 中位数计数 基准时间限制:1 秒 空间限制: ...
- python第五课——流程控制语句
流程控制语句: 分类: 1).顺序结构 2).判断结构解析:如果...否则... 3).循环结构 1.判断结构: 格式分类:三种格式 格式一: ① if 条件表达式: 语句块 ② 执行流程: 计算机会 ...
- 如何在Python中获取当前时间
所属网站分类: python基础 > 模块,库 作者:追梦骚年 链接:http://www.pythonheidong.com/blog/article/68/ 来源:python黑洞网,专注p ...