棋盘模型 + 动态加边
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#define ll long long
#define M 51
#define N 500010
#define mmp make_pair
const int inf = 0x3e3e3e3e;
using namespace std;
int read()
{
int nm = 0, f = 1;
char c = getchar();
for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
return nm * f;
}
char S[M][M];
struct Note
{
int ver, nxt, vi, vj, cap, flow;
}edge[N];
int head[N], cnt = 1, n, s, t, cost, ans;
bool vis[5010];
int dis[5050], sd[5050 * 30], sum[5050 * 30], noteans[5050], upup;
int tota, totb, notea[M][M], noteb[M][M], suma[M * M], sumb[M * M], nowa[M * M], nowb[M * M];
void push(int vi, int vj, int flo, int ver)
{
// cout << vi << " " << vj << " " << ver << "\n";
cnt++; edge[cnt].vi = vi, edge[cnt].ver = ver, edge[cnt].vj = vj, edge[cnt].nxt = head[vi], head[vi] = cnt, edge[cnt].cap = flo;
cnt++; edge[cnt].vi = vj, edge[cnt].ver = -ver, edge[cnt].vj = vi, edge[cnt].nxt = head[vj], head[vj] = cnt;
} bool spfa(int be, int ed)
{
queue<int> q;
for(int i = 0; i <= t; i++) vis[i] = 0, dis[i] = inf;
dis[be] = 0, sum[s] = 0x3e3e3e3e;
q.push(be);
while(!q.empty())
{
int now = q.front();
q.pop();
vis[now] = false;
for(int i = head[now]; i; i = edge[i].nxt)
{
int vj = edge[i].vj;
if(edge[i].flow >= edge[i].cap) continue;
if(dis[vj] > dis[now] + edge[i].ver)
{
dis[vj] = dis[now] + edge[i].ver;
sd[vj] = i;
sum[vj] = min(sum[now], edge[i].cap - edge[i].flow);
if(!vis[vj])
{
vis[vj] = true;
q.push(vj);
}
}
}
}
if(dis[ed] == inf) return 0;
ans += sum[ed];
cost += sum[ed] * dis[ed];
int u = ed, x;
while(u != be)
{
x = sd[u];
int vi = edge[x].vi, vj = edge[x].vj;
if(vi == s && nowa[vj] + 1< suma[vj])
{
nowa[vj]++;
push(s, vj, 1, nowa[vj]);
}
if(vj == t && nowb[vi - tota] + 1 < sumb[vi - tota])
{
nowb[vi - tota]++;
push(vi, t, 1, nowb[vi - tota]);
}
edge[x].flow += sum[ed];
edge[x ^ 1].flow -= sum[ed];
u = edge[x].vi;
}
return true;
}
int main()
{
n = read();
for(int i = 1; i <= n; i++) scanf("%s", S[i] + 1);
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
if(S[i][j] == '.') upup++;
}
}
for(int i = 1; i <= n; i ++)
{
for(int j = 1; j <= n; j++)
{
if(j == 1 || (S[i][j - 1] == '#' && S[i][j] == '.')) tota++;
if(S[i][j] == '#') continue;
suma[tota]++, notea[i][j] = tota;
}
}
for(int j = 1; j <= n; j++)
{
for(int i = 1; i <= n; i++)
{
if(i == 1 || (S[i - 1][j] == '#' && S[i][j] == '.')) totb++;
if(S[i][j] == '#') continue;
sumb[totb]++, noteb[i][j] = totb;
push(notea[i][j], tota + noteb[i][j], 1, 0);
}
}
s = tota + totb + 1, t = s + 1;
for(int i = 1; i <= tota; i++) if(suma[i]) push(s, i, 1, 0);
for(int i = 1; i <= totb; i++) if(sumb[i]) push(i + tota, t, 1, 0);
for(int tim = 1; tim <= upup; tim++)
{
spfa(s, t);
noteans[tim] = cost;
}
int t = read();
while(t--)
{
int x = read();
if(x > upup) puts("0");
else cout << noteans[x] << "\n";
}
return 0;
}
/*
3
...
...
...
5 */

「2017 山东一轮集训 Day4」棋盘(费用流)的更多相关文章

  1. [LOJ#6068]. 「2017 山东一轮集训 Day4」棋盘[费用流]

    题意 题目链接 分析 考虑每个棋子对对应的横向纵向的极大区间的影响:记之前这个区间中的点数为 \(x\) ,那么此次多配对的数量即 \(x\) . 考虑费用流,\(S\rightarrow 横向区间 ...

  2. Loj 6068. 「2017 山东一轮集训 Day4」棋盘

    Loj 6068. 「2017 山东一轮集训 Day4」棋盘 题目描述 给定一个 $ n \times n $ 的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置 $ (x, y),(u, ...

  3. loj6068. 「2017 山东一轮集训 Day4」棋盘 二分图,网络流

    loj6068. 「2017 山东一轮集训 Day4」棋盘 链接 https://loj.ac/problem/6068 思路 上来没头绪,后来套算法,套了个网络流 经典二分图 左边横,右边列 先重新 ...

  4. LOJ 6068「2017 山东一轮集训 Day4」棋盘

    题意 一个 \(n\times n\) 的棋盘上面有若干障碍物. 定义两个棋子可以互相攻击当且仅当这两个棋子的横坐标或纵坐标相等而且中间不能隔着障碍物.(可以隔棋子) 有 \(q\) 次询问,每次询问 ...

  5. loj#6073. 「2017 山东一轮集训 Day5」距离(费用流)

    题意 题目链接 Sol 我们可以把图行列拆开,同时对于行/列拆成很多个联通块,然后考虑每个点所在的行联通块/列联通块的贡献. 可以这样建边 从S向每个行联通块连联通块大小条边,每条边的容量为1,费用为 ...

  6. Loj #6069. 「2017 山东一轮集训 Day4」塔

    Loj #6069. 「2017 山东一轮集训 Day4」塔 题目描述 现在有一条 $ [1, l] $ 的数轴,要在上面造 $ n $ 座塔,每座塔的坐标要两两不同,且为整点. 塔有编号,且每座塔都 ...

  7. 「2017 山东一轮集训 Day4」基因

    设置 \(\sqrt{n}\) 个关键点,维护出关键点到每个右端点之间的答案以及Pam的左指针,每次暴力向左插入元素即可,为了去重,还需要记录一下Pam上每个节点在每个关键点为左端点插入到时候到最左边 ...

  8. Loj #6073.「2017 山东一轮集训 Day5」距离

    Loj #6073.「2017 山东一轮集训 Day5」距离 Description 给定一棵 \(n\) 个点的边带权的树,以及一个排列$ p\(,有\)q $个询问,给定点 \(u, v, k\) ...

  9. 「2017 山东一轮集训 Day5」苹果树

    「2017 山东一轮集训 Day5」苹果树 \(n\leq 40\) 折半搜索+矩阵树定理. 没有想到折半搜索. 首先我们先枚举\(k\)个好点,我们让它们一定没有用的.要满足这个条件就要使它只能和坏 ...

随机推荐

  1. js过滤输入的emoji表情

    因为emoji表情是Unicode编码, 在某些流浪器上会显示乱码, 有的数据库字节不够也无法存储, 网上有很多解决此类问题的办法, 最简单的莫过于将emoji表情替换成文本, 比如 [表情][表情] ...

  2. 干货-递归下降分析器 笔记(具体看Python Cookbook, 3rd edition 的2.19章节)

    import re import collections # 写将要匹配的正则 NUM = r'(?P<NUM>\d+)' PLUS = r'(?P<PLUS>\+)' MIN ...

  3. RedHat6.5创建本地yum源

    拷贝Linux操作系统的rhel-server-6.5-x86_64-dvd.iso镜像到装好的Linux中: #执行挂载命令 mount –o loop /media/rhel-server-6.5 ...

  4. Java通过webservice接口获取天气信息

    通过SOAP请求的方式获取天气信息并解析返回的XML文件. 参考: http://www.webxml.com.cn/WebServices/WeatherWS.asmx import java.io ...

  5. ML平台_饿了么实践

    (转载至:https://zhuanlan.zhihu.com/p/28592540) 说到机器学习.大数据,大家听到的是 Hadoop 和 Spark 居多,它们跟 TensorFlow 是一个什么 ...

  6. MMU实验

    内存管理单元 MMU介绍:权限管理:地址映射 权限管理:内核->A->B 地址空间各不相同 地址映射:多任务系统也是分时系统 虚拟地址(地址空间)->MMU->物理地址 SDR ...

  7. msp430学习笔记-实现开方log等计算及FFT算法(待续)

    MSP430 FFT算法实现 http://bbs.21ic.com/icview-391532-1-1.html http://blog.sina.com.cn/s/blog_6cd2030b010 ...

  8. #ifdef __cplusplus extern "C" { #endif 含义

    转载! 1.在好多程序中我们会遇到下面代码段 #ifdef __cplusplus         extern "C" {         #endif //c语法代码段 #if ...

  9. JDBC相关概念介绍

    一.JDBC相关概念介绍 1.1.数据库驱动 这里的驱动的概念和平时听到的那种驱动的概念是一样的,比如平时购买的声卡,网卡直接插到计算机上面是不能用的,必须要安装相应的驱动程序之后才能够使用声卡和网卡 ...

  10. uoj#119. 【UR #8】决战圆锥曲线

    http://uoj.ac/problem/119 可以认为数据基本随机,于是可以直接用线段树维护,对每个询问在线段树上进行剪枝搜索. #include<bits/stdc++.h> ty ...