题目描述

在一个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;
}

转载于:https://www.cnblogs.com/GXZlegend/p/7493170.html

【bzoj4883】[Lydsy2017年5月月赛]棋盘上的守卫 最小环套树森林相关推荐

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

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

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

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

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

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

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

    Description 在一个n*m的棋盘上要放置若干个守卫.对于n行来说,每行必须恰好放置一个横向守卫:同理对于m列来说,每列 必须恰好放置一个纵向守卫.每个位置放置守卫的代价是不一样的,且每个位置 ...

  5. 【BZOJ 4832】 [Lydsy2017年4月月赛] 抵制克苏恩 期望概率dp

    打记录的题打多了,忘了用开维记录信息了......我们用f[i][j][l][k]表示已经完成了i次攻击,随从3血剩j个,2血剩l个,1血剩k个,这样我们求出每个状态的概率,从而求出他们对答案的贡献并 ...

  6. 【bzoj4881】[Lydsy2017年5月月赛]线段游戏 树状数组+STL-set

    题目描述 quailty和tangjz正在玩一个关于线段的游戏.在平面上有n条线段,编号依次为1到n.其中第i条线段的两端点坐标分别为(0,i)和(1,p_i),其中p_1,p_2,...,p_n构成 ...

  7. Lydsy2017年4月月赛 抵制克苏恩

    Description 小Q同学现在沉迷炉石传说不能自拔.他发现一张名为克苏恩的牌很不公平.如果你不玩 炉石传说,不必担心,小Q同学会告诉你所有相关的细节.炉石传说是这样的一个游戏, 每个玩家拥有一个 ...

  8. BZOJ 4884 [Lydsy2017年5月月赛]太空猫(单调DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4884 [题目大意] 太空猫(SpaceCat)是一款画面精致.玩法有趣的休闲游戏, 你 ...

  9. [bzoj4881][Lydsy2017年5月月赛]线段游戏

    来自FallDream的博客,未经允许,请勿转载,谢谢. quailty和tangjz正在玩一个关于线段的游戏.在平面上有n条线段,编号依次为1到n.其中第i条线段的两端点坐标分别为(0,i)和(1, ...

最新文章

  1. 运动目标检测ViBe算法
  2. C标准库stdlib.h概况
  3. Keil编译产生的RO,RW和ZI是什么
  4. 呆呆键盘手11.14号学到的定位-实现滚动门效果
  5. LAMP搭建Discuz论坛
  6. mysql_load
  7. 【熊猫站群系统@苹果cmsv10/Maccmsv10 站群深度定制版 开发日志】 优雅且高效的友链模块,一键打造强大的蜘蛛池
  8. QCostomPlot 示例注解 1
  9. 计算机在酒店与应用中的展望,对酒店计算机信息管理系统的分析与展望
  10. 2020年实验室安全准入考试
  11. 自调用(自执行)函数的五种写法
  12. Mind+实例5——打地鼠游戏
  13. 我为什么花 1 万多买 MacBook Pro,重点是推荐我常用的开发写作相关的工具
  14. 在VisualBasic6.0中实现0.5数值修约
  15. 攻略| Win10 C盘越用越大 清理工具不管用可试试这个办法
  16. Flink_企业级风控平台架构建设_01
  17. r5 6600h怎么样 相当于什么水平
  18. 北京超融合服务器虚拟化软件,选择超融合一体机还是超融合纯软件?
  19. 我的世界java版启动器怎么安装mod_我的世界MOD怎么安装 手机版MOD启动器下载
  20. 坐拥千万用户,覆盖百余行业,脉脉却挣扎在“塔西佗陷阱”

热门文章

  1. 突破网站对Selenium的屏蔽
  2. 2017年12月六级翻译太湖
  3. conda使用教程简写
  4. Oracle 中 nvl、nvl2、nullif、coalesce、decode 函数的用法详解
  5. 海岸线 LQ-619K 打印机驱动
  6. 微信支付JSAPI(公众号支付)接口调用
  7. 南邮-物联网院计算机网络学习笔记(2022年考试版)
  8. 大学里应该重点学习哪门技术语言
  9. NSView显示颜色的几种方式
  10. web版svg制作工具