题目描述

在一个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. 插入数据返回自增id及插入更新二合一

    原文https://blog.csdn.net/dumzp13/article/details/50984413 JDBC: con.setAutoCommit(false); String sql ...

  2. java通过FreeMarker模板生成Excel文件之.ftl模板制作

    关于怎么通过freemarker模板生成excel的文章很多,关键点在于怎么制作模板文件.ftl 网上的办法是: (1)把Excel模板的格式调好,另存为xml文件 (2)新建一个.ftl文件,把xm ...

  3. js中document的用法小结

    document常用属性: document.title//设置文档标题,与HTNL中的title标签等价 document.bgColor//设置页面背景颜色 document.fgColor//设 ...

  4. css设置内容超出后显示省略号

    1.使用overflow: hidden把超出的内容进行隐藏: 2.然后使用white-space: nowrap设置内容不换行: 3.最后使用text-overflow: ellipsis设置超出内 ...

  5. C语言字符篇(一)字符串转换函数

      #include <stdlib.h>   double atof(const char *nptr);  将字符串转换成双精度浮点数 int atoi(const char *npt ...

  6. sql查询平均下单时间

    SQL查询订单平均审核时长 今天在写一个sql,需求是算一个订单在执行状态中的各个节点的时长 比如在订单中,状态0为开始接单,状态3为已经审核,那么现在需要计算每个客服的平均审核时长 像图中所示:这个 ...

  7. POJ:3685-Matrix

    Matrix Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 7879 Accepted: 2374 Description Gi ...

  8. POJ:2429-GCD & LCM Inverse(素数判断神题)(Millar-Rabin素性判断和Pollard-rho因子分解)

    原题链接:http://poj.org/problem?id=2429 GCD & LCM Inverse Time Limit: 2000MS Memory Limit: 65536K To ...

  9. 3,MongoDB之数据类型

    一.MongoDB 之数据类型 首先我们要先了解一下MongoDB中有什么样的数据类型: Object  ID :Documents 自生成的 _id String: 字符串,必须是utf-8 Boo ...

  10. 以最省内存的方式把大图片加载到内存及获取Exif信息和获取屏幕高度和宽度的新方法

    我们在加载图片时经常会遇到内存溢出的问题,图片太大,我们加载图片时,一般都是用的如下一般方法(加载本地图片): /** * 不作处理,去加载图片的方法,碰到比较大的图片会内存溢出 */ private ...