【bzoj4883】棋盘上的守卫 题解

题目大意

       在一个 n*m 的棋盘上要放置若干个守卫。每行必须恰好放置一个横向守卫,每列必须恰好放置一个纵向守卫。每个位置放置守卫的代价是 w[i][j],且每个位置最多只能放置一个守卫,一个守卫不能同时兼顾行列的防御。请计算控制整个棋盘的最小代价。
       n*m<=1e5, w<=1e9

解法1

       首先考虑基本的网络流模型:
       建两排点,第一排点有 n*m 个,代表每个格子;第二排点有 n+m 个,代表行和列。然后每个格子向其对应的行和列连容量为 1、费用为 w[i][j] 的边,跑最大权匹配。

       据说 zkw 或者 km 什么的大力艹就过了???

解法2

       考虑用贪心来模拟费用流。

       费用流的本质是每次找一条最短的增广路。于是把边按照边权从小到大加入(我是指中间的边,连着源汇的不考虑),假设当前加入的边,权值为 w,左边是 x,它对应的行和列是 i 和 j。
       我们维护第二排点的连通性,这里的连通性不是指原图的连通性,而是我另外弄了个并查集,一开始互不连通。如果我把上面的加入操作视作是给 i 和 j 连上一条边,那么这里的每一条边相当于是第一排的一个点,这个连通性就代表第二排点的匹配情况。假如连通性是一棵树,则连通块内必有一点没被匹配;假如连通性是一个图(我们限制他只能是环套树,即一棵树再连一条边),则连通块内所有点都能匹配。(相当于是把边分给点,环套树是可以分完的,而树会空出一个点)

       那么对于一个加入操作我们分情况讨论:
       1、i 和 j 不连通。那么并查集里面就把它们连起来。假如两个连通块都是树,或者一个树一个图,那当前的 w 就计入答案。
       2、i 和 j 连通,连通情况为一棵树。那就把树更新为图,并把 w 计入答案。
       3、i 和 j 连通,连通情况为一个图。啥也不干。

       这样就用贪心代替费用流了。

你可能感兴趣的:(算法_网络流,算法_贪心)