[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 ...
随机推荐
- Linux dumpe2fs命令详解
dumpe2fs: 查看格式化之后的文件系统信息. dumpe2fs使用 [root@localhost omc]# dumpe2fs --help<BR>dumpe2fs 1.41.12 ...
- Spring Security自定义GrantedAuthority前缀
如果我们正使用Spring Security提供默认的基于方法的权限认证注解如下: @PreAuthorize("hasAnyRole('ADMIN', 'USER')") pub ...
- November 20th 2016 Week 47th Sunday
Learn from yesterday, live for today, look to tomorrow. 学习昨天,活在今天,展望明天. There is always room at the ...
- Zepto的SwipeUp 在 android 和微信 的解决方案
Zepto的SwipeUp 在 android 和微信 的解决方案 时间:2016-04-19 22:20:09 作者:zhongxia 问题解决方案: Q:为什么swipeUp和swipeDown在 ...
- 归并排序(php实现)
<?php function mergeSort(&$arr){ $len = count($arr); msort($arr,0,$len-1); } function msort(& ...
- [转] pom.xml 配置详解
From:http://blog.csdn.net/ithomer/article/details/9332071 Maven是一个项目管理工具,通过pom.xml来实现. pom.xml 配置文件 ...
- BZOJ1001: [BeiJing2006]狼抓兔子【最短路+对偶图】
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1001 1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Se ...
- C++编译器符号表有哪些内容?
http://blog.csdn.net/wangbingcsu/article/details/48340479 C++编译器符号表有哪些内容? 很早就想写一篇关于符号表的学习小结,可是迟迟不能下笔 ...
- js(window.open)浏览器弹框居中显示
<span style="background-color: rgb(204, 204, 204);"><html> <meta name=" ...
- nuxt 脚手架创建nuxt项目中不支持es6语法的解决方案
node本身并不支持es6语法,我们通常在vue项目中使用es6语法,是因为,我们使用babel做过处理, 为了让项目支持es6语法,我们必须同时使用babel 去启动我们的程序,所以再启动程序中加 ...