Gym101194J Mr.Panda and TubeMaster 二分图、费用流
看到这张图,是一个网格图,而且有回路限制,不难想到黑白染色。
一般来说我们对一张图黑白染色之后都是黑色点向白色点连边,但是这道题往这边想似乎就想不出建图方法了,因为“一个格子强制流满\(2\)的流”和“权值和最大”无法同时在这张图上体现出来。
实际上这道题黑色和白色、白色和黑色之间都需要连边。
我们令左右方向的管道全部从黑色向白色连,上下方向的管道全部从白色往黑色连。也就是对于每一个点拆成入点和出点,对于黑色的入点,向其左右方向的白色出点连边;对于白色的入点,向其上下方向的黑色出点连边。连边的容量为\(1\)、费用为管道的价值。
然后考虑强制选择的限制。对于某个点,如果它没有被强制限制,就将其入点和出点之间连一条容量为\(1\)、费用为\(0\)的边,表示它能够自己和自己匹配。
这样就可以跑最大费用最大流了。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<algorithm>
#include<cstring>
#include<iomanip>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<vector>
#include<cmath>
#include<random>
#include<cassert>
#define INF 0x3f3f3f3f
//This code is written by Itst
using namespace std;
const int MAXN = 1e5 + 7 , MAXM = 1e6 + 7;
struct Edge{
int end , upEd , f , c;
}Ed[MAXM];
int head[MAXN] , val[32][32][2] , id[32][32][2];
int N , M , S , T , cntEd = 1;
bool mrk[32][32];
queue < int > q;
inline void addEd(int a , int b , int c , int d = 0){
Ed[++cntEd].end = b;
Ed[cntEd].upEd = head[a];
Ed[cntEd].f = c;
Ed[cntEd].c = d;
head[a] = cntEd;
}
inline void addE(int a , int b , int c , int d = 0 , bool f = 0){
addEd(a , b , c , d); addEd(b , a , c * f , -d);
}
bool vis[MAXN];
int dis[MAXN] , pre[MAXN] , flo[MAXN];
inline bool SPFA(){
memset(dis , -0x3f , sizeof(dis));
dis[S] = 0;
while(!q.empty())
q.pop();
q.push(S);
flo[S] = INF;
while(!q.empty()){
int t = q.front();
q.pop();
vis[t] = 0;
for(int i = head[t] ; i ; i = Ed[i].upEd)
if(Ed[i].f && dis[Ed[i].end] < dis[t] + Ed[i].c){
dis[Ed[i].end] = dis[t] + Ed[i].c;
flo[Ed[i].end] = min(Ed[i].f , flo[t]);
pre[Ed[i].end] = i;
if(!vis[Ed[i].end]){
vis[Ed[i].end] = 1;
q.push(Ed[i].end);
}
}
}
return dis[T] != dis[T + 1];
}
int EK(){
int ans = 0 , flow = 0;
while(SPFA()){
int cur = T , sum = 0;
while(cur != S){
sum += Ed[pre[cur]].c;
Ed[pre[cur]].f -= flo[T];
Ed[pre[cur] ^ 1].f += flo[T];
cur = Ed[pre[cur] ^ 1].end;
}
flow += flo[T];
ans += sum * flo[T];
}
return flow == N * M ? ans : -1;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in" , "r" , stdin);
//freopen("out" , "w" , stdout);
#endif
ios::sync_with_stdio(0);
int t , E , x , y , Case = 0;
for(cin >> t ; t ; --t){
cin >> N >> M;
T = 0; cntEd = 1;
memset(head , 0 , sizeof(head));
memset(mrk , 0 , sizeof(mrk));
for(int i = 1 ; i <= N ; ++i)
for(int j = 1 ; j <= M ; ++j){
id[i][j][0] = ++T; id[i][j][1] = ++T;
}
for(int i = 1 ; i <= N ; ++i)
for(int j = 1 ; j < M ; ++j){
cin >> x;
if(!((i + j) & 1)) val[i][j][1] = x;
else val[i][j + 1][0] = x;
}
for(int i = 1 ; i < N ; ++i)
for(int j = 1 ; j <= M ; ++j){
cin >> x;
if((i + j) & 1) val[i][j][1] = x;
else val[i + 1][j][0] = x;
}
++T;
for(cin >> E ; E ; --E){cin >> x >> y; mrk[x][y] = 1;}
for(int i = 1 ; i <= N ; ++i)
for(int j = 1 ; j <= M ; ++j){
addE(S , id[i][j][0] , 1);
addE(id[i][j][1] , T , 1);
if(!mrk[i][j]) addE(id[i][j][0] , id[i][j][1] , 1);
if((i + j) & 1){
if(i != 1)
addE(id[i][j][0] , id[i - 1][j][1] , 1 , val[i][j][0]);
if(i != N)
addE(id[i][j][0] , id[i + 1][j][1] , 1 , val[i][j][1]);
}
else{
if(j != 1)
addE(id[i][j][0] , id[i][j - 1][1] , 1 , val[i][j][0]);
if(j != M)
addE(id[i][j][0] , id[i][j + 1][1] , 1 , val[i][j][1]);
}
}
int t = EK();
cout << "Case #" << ++Case << ": ";
if(t == -1) cout << "Impossible\n";
else cout << t << '\n';
}
return 0;
}
Gym101194J Mr.Panda and TubeMaster 二分图、费用流的更多相关文章
- China Final J - Mr.Panda and TubeMaster
和一般的管道不同 不能类似“无限之环”或者“弯弯国”的建图,因为这两个题都是某些位置必须有,或者必须没有 但是本题可以有的位置随意,不能限制某个位置要么流2,要么流0,(实际上可能流了1过去) 所以建 ...
- ICPC 2016 China Final J. Mr.Panda and TubeMaster【最大费用最大流】
有一种限制下界强制选的,但是也可以不用 把每个格点拆成两个,一个连s一个连t,对于不是必选的连中间连流量1费用0边表示不选,然后黑白染色,黑点连横着白点连竖着,边权就是这条水管的权值,然后跑最大费用最 ...
- 【费用流】 ICPC 2016 China Final J. Mr.Panda and TubeMaster
表示“必须选”的模型 题目大意 题目分析 一个格子有四种方式看上去很难处理.将横竖两个方向分开考虑,会发现:因为收益只与相邻格子是否连通有关,所以可以将一个格子拆成表示横竖两个方向的,互相独立的点. ...
- J - Mr.Panda and TubeMaster
题解 我们可以把每个格子拆成两个点,一个表示横向的,一个表示纵向的,相邻的格子横向和纵向连边. 如果直接按照题意做的话,我们应当在横向和纵向的点之间连边,有限制的边设下界为1,然后跑可行流. 或者考虑 ...
- POJ2195 Going Home[费用流|二分图最大权匹配]
Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 22088 Accepted: 11155 Desc ...
- BZOJ.4514.[SDOI2016]数字配对(费用流SPFA 二分图)
BZOJ 洛谷 \(Solution\) 很显然的建二分图后跑最大费用流,但有个问题是一个数是只能用一次的,这样二分图两部分都有这个数. 那么就用两倍的.如果\(i\)可以向\(j'\)连边,\(j\ ...
- 【BZOJ 3308】 3308: 九月的咖啡店 (费用流|二分图最大权匹配)
3308: 九月的咖啡店 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 244 Solved: 86 Description 深绘里在九份开了一家咖 ...
- 【LA2238 训练指南】固定分区内存管理 【二分图最佳完美匹配,费用流】
题意 早期的多程序操作系统常把所有的可用内存划分为一些大小固定的区域,不同的区域一般大小不同,而所有区域的大小之和为可用内存的大小.给定一些程序,操作系统需要给每个程序分配一个区域,使得他们可以同时执 ...
- 【LA4043 训练指南】蚂蚁 【二分图最佳完美匹配,费用流】
题意 给出n个白点和n个黑点的坐标,要求用n条不相交的线段把他们连接起来,其中每条线段恰好连接一个白点和一个黑点,每个点恰好连接一条线段. 分析 结点分黑白,很容易想到二分图.其中每个白点对应一个X结 ...
随机推荐
- python 标准类库-数据类型之集合-容器数据类型
标准类库-数据类型之集合-容器数据类型 by:授客 QQ:1033553122 Counter对象 例子 >>> from collections import Counter ...
- Windows上通过bat调用jmx进行循环运行
1.jmx测试脚本中有两个线程组: 1)第一个线程组:模拟60台客户机并发像服务器发送上报请求,需要调用线程组的循环运行 2)第二个线程组:60台客户机上线后,模拟管理平台对客户机进行基础操作,如:创 ...
- Android 内存管理中的 Shallow heap Retained heap
所有包含Heap Profling功能的工具(MAT,Yourkit,JProfiler,TPTP等)都会使用到两个名词,一个是Shallow heap Size,另一个是 Retained heap ...
- Apache httpd.conf配置文件主要内容解释
1 ServerRoot 配置 ["ServerRoot" 主要用于指定Apache的安装路径,此选项参数值在安装Apache时系统会自动把Apache的路径写入.Windows安 ...
- 我喜欢的vs+va快捷键
拿到新版的vs,我首先会安装va,然后自定义快捷键.现在有些快捷键被系统占用,可以先remove掉,然后换成自己熟悉的快捷键.需要做到常用快捷键两个按键即可. alt+Q:文件中查询,复杂查询 ctr ...
- 洗礼灵魂,修炼python(86)--全栈项目实战篇(12)—— 利用socket实现文件传输/并发式聊天
由于本篇博文的项目都很简单,所以本次开个特例,本次解析两个项目,但是都很简单的 项目一:用socket实现文件传输 本项目很简单,作为小项目的预热的,前面刚学完socket,这里马上又利用socket ...
- Linux核心调度器之周期性调度器scheduler_tick--Linux进程的管理与调度(十八)
我们前面提到linux有两种方法激活调度器:核心调度器和 周期调度器 一种是直接的, 比如进程打算睡眠或出于其他原因放弃CPU 另一种是通过周期性的机制, 以固定的频率运行, 不时的检测是否有必要 因 ...
- python3使用selenium + Chrome基础操作代码
selenium是Python的第三方库,使用前需要安装.但是如果你使用的是anaconda,就可以省略这个步骤,为啥?自带,任性. 安装命令: pip install selenium (一)使用s ...
- vue原理简介
写vue也有一段时间了,对vue的底层原理虽然有一些了解,这里总结一下. vue.js中有两个核心功能:响应式数据绑定,组件系统.主流的mvc框架都实现了单向数据绑定,而双向绑定无非是在单向绑定基础上 ...
- 《Java大学教程》—第18章 高级图形编程
自测题:1. 在图形应用程序中为用户提供选择的多种方式:P433下拉菜单(pull-down menu).弹出式菜单(pop-up menu).对话框窗口(dialogue window).单选 ...