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结 ...
随机推荐
- 为libevent添加websocket支持(上)
在跨平台网络基础库中,libevent与asio近年来使用比较广泛.asio对boost的依赖太大,个人认为发展前途堪忧,尤其asio对http没有很好的支持也是缺点之一. libevent对http ...
- 标注的SQL拼接语句
方案一 exec sp_executesql N' SELECT T0.[WtmCode], T3.[opCode], T3.[opValue], T3.[CondId] FROM [dbo].[OW ...
- ajax参数
$.ajax({ type: "GET", url: "Login.ashx", dataType: "text", cache: fals ...
- 自动化测试基础篇--Selenium鼠标键盘事件
摘自https://www.cnblogs.com/sanzangTst/p/7477382.html 前面几篇文章我们学习了怎么定位元素,同时通过实例也展示了怎么切换到iframe,怎么输入用户名和 ...
- Android项目的targetSDK>=23,在低于Android6.0的部分测试机(类似华为)上运行时出现的系统权限问题
相信大家对Android6.0以上的动态权限已经有所了解,很多童鞋也已经跃跃欲试地将自己项目的targetSDK升级到了23及其以上,很不幸的是我也成为了其中一员,然而我还是图样图森破了,升级之后的问 ...
- PHP is much better than you think
Rants about PHP are everywhere, and they even come from smart guys.When Jeff Atwood wrote yet anothe ...
- win10升级后蓝牙不见了,设备管理器里没有,多了个串行控制器里的未知USB设备?
win10更新后,蓝牙功能不见了,也没有打开的选项,设备管理器里也没有,多了个未知USB设备,重启无效,重装蓝牙驱动无效,BIOS中的Bluetooth是开的. 试了网上能找到的所有方法,包括更新wi ...
- LeetCode算法题-First Bad Version(Java实现-三种解法)
这是悦乐书的第200次更新,第210篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第66题(顺位题号是278).您是产品经理,目前领导团队开发新产品.不幸的是,您产品的最 ...
- python 初始socket
一.网络基础 1.c\s架构:客户端英文名称:Client(使用服务端的服务),服务端英文名称:Server 软件c\s架构:QQ.微信.优酷.暴风影音.浏览器(IE.火狐,360浏览器等): 软件b ...
- SpringBoot2.0 最简单的 idea 快速创建项目
第一步 第二步 第三步 以上就是idea快速创建springboot的方法,创建之后等maven 依赖下载完成,就可以使用