题目描述

在一个n*m的棋盘上要放置若干个守卫。对于n行来说,每行必须恰好放置一个横向守卫;同理对于m列来说,每列必须恰好放置一个纵向守卫。每个位置放置守卫的代价是不一样的,且每个位置最多只能放置一个守卫,一个守卫不能同时兼顾行列的防御。请计算控制整个棋盘的最小代价。

输入

第一行包含两个正整数n,m(2<=n,m<=100000,n*m<=100000),分别表示棋盘的行数与列数。
接下来n行,每行m个正整数
其中第i行第j列的数w[i][j](1<=w[i][j]<=10^9)表示在第i行第j列放置守卫的代价。

输出

输出一行一个整数,即占领棋盘的最小代价。

样例输入

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月月赛]棋盘上的守卫 最小环套树森林的更多相关文章

  1. [bzoj4883][Lydsy2017年5月月赛]棋盘上的守卫

    来自FallDream的博客,未经允许,请勿转载, 谢谢. 在一个n*m的棋盘上要放置若干个守卫.对于n行来说,每行必须恰好放置一个横向守卫:同理对于m列来说,每列 必须恰好放置一个纵向守卫.每个位置 ...

  2. [BZOJ4883][Lydsy1705月赛]棋盘上的守卫[最小基环树森林]

    题意 有一大小为 \(n*m\) 的棋盘,要在一些位置放置一些守卫,每个守卫只能保护当前行列之一,同时在每个格子放置守卫有一个代价 \(w\) ,问要使得所有格子都能够被保护,需要最少多少的代价. \ ...

  3. 【BZOJ4883】[Lydsy2017年5月月赛]棋盘上的守卫 KM算法

    [BZOJ4883][Lydsy2017年5月月赛]棋盘上的守卫 Description 在一个n*m的棋盘上要放置若干个守卫.对于n行来说,每行必须恰好放置一个横向守卫:同理对于m列来说,每列 必须 ...

  4. 【题解】BZOJ4883: [Lydsy1705月赛]棋盘上的守卫(最小生成基环森林)

    [题解]BZOJ4883: [Lydsy1705月赛]棋盘上的守卫(最小生成基环森林) 神题 我的想法是,每行每列都要有匹配且一个点只能匹配一个,于是就把格点和每行每列建点出来做一个最小生成树,但是不 ...

  5. BZOJ 4883 [Lydsy2017年5月月赛]棋盘上的守卫(最小生成环套树森林)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4883 [题目大意] 在一个n*m的棋盘上要放置若干个守卫. 对于n行来说,每行必须恰好 ...

  6. BZOJ4883: [Lydsy1705月赛]棋盘上的守卫(最小环套树森林&优化定向问题)

    4883: [Lydsy1705月赛]棋盘上的守卫 Time Limit: 3 Sec  Memory Limit: 256 MBSubmit: 475  Solved: 259[Submit][St ...

  7. BZOJ4883 棋盘上的守卫(环套树+最小生成树)

    容易想到网络流之类的东西,虽然范围看起来不太可做,不过这提供了一种想法,即将行列分别看做点.那么我们需要找一种连n+m条边的方案,使得可以从每条边中选一个点以覆盖所有点.显然每个点至少要连一条边.于是 ...

  8. bzoj4883 [Lydsy1705月赛]棋盘上的守卫 最小生成基环树森林

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4883 题解 每一行和每一列都必须要被覆盖. 考虑对于每一行和每一列都建立一个点,一行和一列之间 ...

  9. BZOJ4886: [Lydsy1705月赛]叠塔游戏(环套树森林&贪心)

    4886: [Lydsy1705月赛]叠塔游戏 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 198  Solved: 76[Submit][Stat ...

随机推荐

  1. 17、SpringBoot------整合dubbo

    SpringBoot整合Dubbo+Zookeaper 1.安装运行zookeeper (1)下载zookeeper 官网:http://zookeeper.apache.org/ (2)解压缩 (3 ...

  2. 基于java开发的开源代码GPS北斗位置服务监控平台

    最近在研究位置服务平台,基于全球卫星定位技术(GNSS).互联网技术.空间地理信息技术(GIS).3G/4G无线通信技术,面向全国公众用户建立大容量.实时.稳定的位置信息服务运营平台.实现管理目标的实 ...

  3. CSU 1216异或最大值 (0-1 trie树)

    Description 给定一些数,求这些数中两个数的异或值最大的那个值 Input 多组数据.第一行为数字个数n,1 <= n <= 10 ^ 5.接下来n行每行一个32位有符号非负整数 ...

  4. cordova创建工程添加插件

    创建工程 phonegap创建工程 代码 用以创建自己需要的  工程名   ; 报名  ;类名 ; 应用名 cordova create hello com.example.hello HelloWo ...

  5. springMVC入门二

    一.准备工作 参考springMVC入门一,搭建maven项目如下: 前台结构如下: 项目介绍:使用springMVC实现前后台数据交互,例如controller返回json,页面传入pojo 二.具 ...

  6. Gulp工具

    Gulp是一个基于node开发的构建工具. gulp本身是不进行任何构建任务,是通过gulp的一些列插件完成: gulp-less  编译LESS文件: gulp-autoprefix  添加css私 ...

  7. 天气预报api-汇总

    和风天气 https://www.heweather.com/

  8. 【jQeury】input输入框状态,input事件,blur事件,focus事件

    //输入框正在输入时 $("#test1").on('input',function(){ alert('正在输入'); }) //输入框得到焦点时 $("#test2& ...

  9. 生产-消费模式的synchronized和lock实现(十)

    lock: package com.net.thread.lock; import java.util.concurrent.locks.Condition; import java.util.con ...

  10. PLC状态机编程-如何在STL中使用状态机

    搞PLC编程多年,一直不知道状态机,学习matlab后,发现状态机编程异常方便,过去很多编程时的疑惑豁然开朗起来.今天跟大家分享一下如何在STL中使用状态机. 下面是用状态机描述的控制任务. 这个状态 ...