【bzoj4930】棋盘 费用流
题目描述
输入
输出
样例输入
4
..#.
####
..#.
..#.
1
7
样例输出
2
题解
费用流, bzoj4554 的强化版
按照那道题的思路,把相互影响的行和列的部分拿出来,同一个点的行部分和列部分之间连边。
不过这道题是固定棋子数,问最小的影响的棋子对数。
考虑,一个行或列的部分,如果存在k个棋子,那么相互影响的棋子对数为$\frac{k(k-1)}2$对(两个棋子之间隔着其它棋子也算相互影响)。
所以我们可以使用拆边法来解决,从S到行的部分、从列的部分到T连d条边,其中d为该部分的位置数。第i条边的费用为$\frac{i(i-1)}2-\frac{(i-1)(i-2)}2=i-1$。
然后跑费用流。在此过程中,由于每条增广路的容量必定为1,所以相当于每次多放置了一个棋子。这样我们可以只跑一次EK费用流即可预处理出所有答案,然后再$O(1)$回答。
时间有点长但可以过,可以动态加边来提高效率(这里懒了没有写)
#include <cstdio>
#include <cstring>
#include <queue>
#define N 6010
#define M 1200010
#define inf 0x3f3f3f3f
using namespace std;
queue<int> q;
int map[60][60] , bx[60][60] , tx , by[60][60] , ty , sx[N] , sy[N] , head[N] , to[M] , val[M] , cost[M] , next[M] , cnt = 1 , s , t , dis[N] , from[N] , pre[N] , ans[N];
char str[60];
void add(int x , int y , int v , int c)
{
to[++cnt] = y , val[cnt] = v , cost[cnt] = c , next[cnt] = head[x] , head[x] = cnt;
to[++cnt] = x , val[cnt] = 0 , cost[cnt] = -c , next[cnt] = head[y] , head[y] = cnt;
}
bool spfa()
{
int x , i;
memset(from , -1 , sizeof(from));
memset(dis, 0x3f , sizeof(dis));
dis[s] = 0 , q.push(s);
while(!q.empty())
{
x = q.front() , q.pop();
for(i = head[x] ; i ; i = next[i])
if(val[i] && dis[to[i]] > dis[x] + cost[i])
dis[to[i]] = dis[x] + cost[i] , from[to[i]] = x , pre[to[i]] = i , q.push(to[i]);
}
return ~from[t];
}
void mincost()
{
int k = 0 , i;
while(spfa())
{
k ++ , ans[k] = ans[k - 1] + dis[t];
for(i = t ; i != s ; i = from[i]) val[pre[i]] -- , val[pre[i] ^ 1] ++ ;
}
}
int main()
{
int n , q , i , j , x;
scanf("%d" , &n);
for(i = 1 ; i <= n ; i ++ )
{
scanf("%s" , str + 1);
for(j = 1 ; j <= n ; j ++ ) map[i][j] = (str[j] == '#');
}
for(i = 1 ; i <= n ; i ++ )
{
tx ++ ;
for(j = 1 ; j <= n ; j ++ ) bx[i][j] = tx , sx[tx] ++ , tx += map[i][j];
}
for(j = 1 ; j <= n ; j ++ )
{
ty ++ ;
for(i = 1 ; i <= n ; i ++ ) by[i][j] = ty , sy[ty] ++ , ty += map[i][j];
}
s = 0 , t = tx + ty + 1;
for(i = 1 ; i <= tx ; i ++ )
for(j = 0 ; j < sx[i] ; j ++ )
add(s , i , 1 , j);
for(i = 1 ; i <= ty ; i ++ )
for(j = 0 ; j < sy[i] ; j ++ )
add(i + tx , t , 1 , j);
for(i = 1 ; i <= n ; i ++ )
for(j = 1 ; j <= n ; j ++ )
if(!map[i][j])
add(bx[i][j] , by[i][j] + tx , 1 , 0);
mincost();
scanf("%d" , &q);
while(q -- ) scanf("%d" , &x) , printf("%d\n" , ans[x]);
return 0;
}
【bzoj4930】棋盘 费用流的更多相关文章
- [LOJ#6068]. 「2017 山东一轮集训 Day4」棋盘[费用流]
题意 题目链接 分析 考虑每个棋子对对应的横向纵向的极大区间的影响:记之前这个区间中的点数为 \(x\) ,那么此次多配对的数量即 \(x\) . 考虑费用流,\(S\rightarrow 横向区间 ...
- 「2017 山东一轮集训 Day4」棋盘(费用流)
棋盘模型 + 动态加边 #include<cstdio> #include<algorithm> #include<iostream> #include<cs ...
- LOJ.6068.[2017山东一轮集训Day4]棋盘(费用流zkw)
题目链接 考虑两个\(\#\)之间产生的花费是怎样的.设这之间放了\(k\)个棋子,花费是\(\frac{k(k-1)}{2}\). 在\((r,c)\)处放棋子,行和列会同时产生花费,且花费和该行该 ...
- 【BZOJ4930】棋盘 拆边费用流
[BZOJ4930]棋盘 Description 给定一个n×n的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置(x,y),(u,v)能互相攻击当前仅 当满足以下两个条件: 1:x=u或y ...
- BZOJ4930: 棋盘
BZOJ4930: 棋盘 https://lydsy.com/JudgeOnline/problem.php?id=4930 分析: 基本上就是游戏那道题加上费用流了,所以没啥好说的. 记得两边都是拆 ...
- ACdream 1128 Maze(费用流)
题目链接:http://acdream.info/problem?pid=1128 Problem Description wuyiqi陷入了一个迷宫中,这个迷宫是由N*M个格子组成的矩阵.每个格子上 ...
- 洛谷P4003 无限之环(infinityloop)(网络流,费用流)
洛谷题目传送门 题目 题目描述 曾经有一款流行的游戏,叫做 Infinity Loop,先来简单的介绍一下这个游戏: 游戏在一个 n ∗ m 的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在格 ...
- BZOJ2673 [Wf2011]Chips Challenge 费用流 zkw费用流 网络流
https://darkbzoj.cf/problem/2673 有一个芯片,芯片上有N*N(1≤N≤40)个插槽,可以在里面装零件. 有些插槽不能装零件,有些插槽必须装零件,剩下的插槽随意. 要求装 ...
- 【BZOJ2668】[cqoi2012]交换棋子 费用流
[BZOJ2668][cqoi2012]交换棋子 Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列 ...
随机推荐
- MySQL常用命令和语句
1.常用SQL语句 1)常用函数/*type可取值为:MICROSECONDSECONDMINUTEHOURDAYWEEKMONTHQUARTERYEARSECOND_MICROSECONDMINUT ...
- 洛谷 1164 小A点菜
题目背景 uim神犇拿到了uoi的ra(镭牌)后,立刻拉着基友小A到了一家……餐馆,很低端的那种. uim指着墙上的价目表(太低级了没有菜单),说:“随便点”. 题目描述 不过uim由于买了一些辅(e ...
- The Django Book - 第四章 模板
使用模板的最基本方式:1.根据原始模板代码字符串创建一个Template对象2. 使用字典创建一套Context变量3. 调用Template对象的render方法,传入Context变量参数 In ...
- Google Colab调用cv2.imshow奔溃
当我在Google Colab运行如下代码 import cv2 import numpy as np image = cv2.imread('a.jpg') cv2.imshow('original ...
- C-基础:表达式中存在有符号类型和无符号类型时,都自动转换为无符号类型
void foo(void) { unsigned ; ; (a+b > ) puts("> 6") : puts("<= 6"); } 答案 ...
- SniperOJ-leak-advanced-x86-64
借助DynELF实现无libc的漏洞利用小结 1.leak-advance与leak的区别在于一个可用函数是write,一个可用函数是puts.write比puts更容易利用,虽然write需要的参数 ...
- C#获得DataTable的key值
//获得dataTable的key值 List<string> keyList = new List<string>(); ; i < dt.Columns.Count; ...
- visibilitychange 标签可见性
var pageVisibility = document.visibilityState;// 监听 visibility change 事件document.addEventListener('v ...
- c++ 当输入的数据不符合数据类型时,清理输入流
if (!cin) { cin.clear(); while (cin.get() != '\n') continue; cout << "Bad input; input pr ...
- Bzoj 1088: [SCOI2005]扫雷Mine (DP)
Bzoj 1088: [SCOI2005]扫雷Mine 怒写一发,算不上DP的游戏题 知道了前\(i-1\)项,第\(i\)项会被第二列的第\(i-1\)得知 设\(f[i]\)为第一列的第\(i\) ...