【bzoj4883】[Lydsy2017年5月月赛]棋盘上的守卫 最小环套树森林
题目描述
输入
输出
样例输入
3 4
1 3 10 8
2 1 9 2
6 7 4 6
样例输出
19
题解
最小环套树森林
首先一眼费用流,然而数据量过大直接卡掉(同时卡掉的还有zkw费用流= =)(跪烂那些用KM算法水过的dalao。。。)
然后经过观察可以发现,如果在行列之间连边,那么答案构成的一定是一个环套树森林。
证明:设行数+列数为n,则构成的图中,点数和边数都为n。如果把每条边选择的方案看作是边的方向的话(a/b中选a看作a->b),那么每个点的出度一定均为1。这样的图一定是环套树森林。因此命题得证。
然后要求的就是无向图的最小环套树森林。
很容易发现环套树森林也是一个拟阵,拟阵最优化问题即可使用贪心算法(Kruscal)求解。
那么本题就和求最小生成树的方法一样了,按边权排序,从小到大加。只需要在原并查集的基础之上,维护每个连通块是否有环,连边时判断即可。
时间复杂度$O(nm\log nm)$
#include <cstdio>
#include <algorithm>
#define N 100010
using namespace std;
struct data
{
int x , y , z;
bool operator<(const data &a)const {return z < a.z;}
}a[N];
int f[N] , c[N];
int find(int x)
{
return x == f[x] ? x : f[x] = find(f[x]);
}
int main()
{
int n , m , i , j , tx , ty;
long long ans = 0;
scanf("%d%d" , &n , &m);
for(i = 1 ; i <= n ; i ++ )
for(j = 1 ; j <= m ; j ++ )
scanf("%d" , &a[(i - 1) * m + j].z) , a[(i - 1) * m + j].x = i , a[(i - 1) * m + j].y = j + n;
sort(a + 1 , a + n * m + 1);
for(i = 1 ; i <= n + m ; i ++ ) f[i] = i;
for(i = 1 ; i <= n * m ; i ++ )
{
tx = find(a[i].x) , ty = find(a[i].y);
if(tx == ty && !c[tx]) c[tx] = 1 , ans += a[i].z;
if(tx != ty && !(c[tx] && c[ty])) f[tx] = ty , c[ty] |= c[tx] , ans += a[i].z;
}
printf("%lld\n" , ans);
return 0;
}
【bzoj4883】[Lydsy2017年5月月赛]棋盘上的守卫 最小环套树森林的更多相关文章
- [bzoj4883][Lydsy2017年5月月赛]棋盘上的守卫
来自FallDream的博客,未经允许,请勿转载, 谢谢. 在一个n*m的棋盘上要放置若干个守卫.对于n行来说,每行必须恰好放置一个横向守卫:同理对于m列来说,每列 必须恰好放置一个纵向守卫.每个位置 ...
- [BZOJ4883][Lydsy1705月赛]棋盘上的守卫[最小基环树森林]
题意 有一大小为 \(n*m\) 的棋盘,要在一些位置放置一些守卫,每个守卫只能保护当前行列之一,同时在每个格子放置守卫有一个代价 \(w\) ,问要使得所有格子都能够被保护,需要最少多少的代价. \ ...
- 【BZOJ4883】[Lydsy2017年5月月赛]棋盘上的守卫 KM算法
[BZOJ4883][Lydsy2017年5月月赛]棋盘上的守卫 Description 在一个n*m的棋盘上要放置若干个守卫.对于n行来说,每行必须恰好放置一个横向守卫:同理对于m列来说,每列 必须 ...
- 【题解】BZOJ4883: [Lydsy1705月赛]棋盘上的守卫(最小生成基环森林)
[题解]BZOJ4883: [Lydsy1705月赛]棋盘上的守卫(最小生成基环森林) 神题 我的想法是,每行每列都要有匹配且一个点只能匹配一个,于是就把格点和每行每列建点出来做一个最小生成树,但是不 ...
- BZOJ 4883 [Lydsy2017年5月月赛]棋盘上的守卫(最小生成环套树森林)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4883 [题目大意] 在一个n*m的棋盘上要放置若干个守卫. 对于n行来说,每行必须恰好 ...
- BZOJ4883: [Lydsy1705月赛]棋盘上的守卫(最小环套树森林&优化定向问题)
4883: [Lydsy1705月赛]棋盘上的守卫 Time Limit: 3 Sec Memory Limit: 256 MBSubmit: 475 Solved: 259[Submit][St ...
- BZOJ4883 棋盘上的守卫(环套树+最小生成树)
容易想到网络流之类的东西,虽然范围看起来不太可做,不过这提供了一种想法,即将行列分别看做点.那么我们需要找一种连n+m条边的方案,使得可以从每条边中选一个点以覆盖所有点.显然每个点至少要连一条边.于是 ...
- bzoj4883 [Lydsy1705月赛]棋盘上的守卫 最小生成基环树森林
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4883 题解 每一行和每一列都必须要被覆盖. 考虑对于每一行和每一列都建立一个点,一行和一列之间 ...
- BZOJ4886: [Lydsy1705月赛]叠塔游戏(环套树森林&贪心)
4886: [Lydsy1705月赛]叠塔游戏 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 198 Solved: 76[Submit][Stat ...
随机推荐
- git 简单使用(待完善)
git是一个分布式版本控制器,简单来说就是可以记录每次代码的修改和提交,方便我们查看修改记录和版本的回退 工作流程 基本概念 仓库 git 是一个分布式版本控制器,其单位就是仓库,每个仓库就是当前gi ...
- 打包时ElementUI使vendor.js文件体量过大优化方法
<h1> 1.在index.html中以CDN的方式引入 </h1> <p> 引入的时候注意:要先在引入之前引入VUE否则会报undedined prototype ...
- JavaScript 十行原生代码实现复制内容到剪贴板
十行原生代码,不引入任何 JS 库,目前大部分浏览器与移动平台都可兼容. function copyToClipboard(value, callback) { var textarea = docu ...
- avalon.js的循环操作在表格中的应用
avalon.js的循环操作在表格中的应用 一个JAVA开发,因为做的门户系统中,数据的展示加载的速度很影响使用效果,想到的是尽量少的请求后台,然后接触到了avalon,看介绍这是一个很轻很轻的MVV ...
- LeetCode106. Construct Binary Tree from Inorder and Postorder Traversal
题目 根据一棵树的中序遍历与后序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 例如,给出 中序遍历 inorder = [9,3,15,20,7] 后序遍历 postorder = [9, ...
- Open closed principle
#include <iostream> using namespace std; class Book { public: string getContents() { return &q ...
- 用 js 写一个获取随机颜色的程序
function getColor(){ var color="#"; for(var i=0;i<6;i++){ color+=(Math.random()*16 | 0) ...
- c#常用数据结构解析【转载】
引用:http://blog.csdn.net/suifcd/article/details/42869341 前言:可能去过小匹夫博客的盆油们读过这篇对于数据结构的总结,但是小匹夫当时写那篇文章的时 ...
- python网络爬虫入门范例
python网络爬虫入门范例 Windows用户建议安装anaconda,因为有些套件难以安装. 安装使用pip install * 找出所有含有特定标签的HTML元素 找出含有特定CSS属性的元素 ...
- strak组件(3):URL别名的优化
将生成URL别名的功能进行解耦.效果和上一节的一样. 效果图: 新增函数 get_url_name(self, param) # 生成url别名,需要一个参数(list/add/edit/delete ...