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结 ... 
随机推荐
- Android为TV端助力 计算每个目录剩余空间丶总空间以及SD卡剩余空间
			ublic class MemorySpaceCheck { /** * 计算剩余空间 * @param path * @return */ public static String getAvail ... 
- Vue之axios请求数据
			引入文件 <script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"> ... 
- log4j.properties配置说明
			log4j.properties配置说明 1. log4j配置 # ALL,DEBUG,INFO,WARN,ERROR,FATAL,OFF LOG_LEVEL=INFO log4j.rootLogge ... 
- 使用Visual Studio Team Services敏捷规划和项目组合管理(五)——组合管理
			使用Visual Studio Team Services敏捷规划和项目组合管理(五)--组合管理 组合待办事项为产品所有者提供关于几个敏捷特性团队工作的洞察.产品所有者可以将高优先级的目标定义为Ep ... 
- MSSQL sql server order by 1,2 的具体含义
			转自:http://www.maomao365.com/?p=5416 摘要: order by 1,2 的含义是对表的第一列 按照从小到大的顺序进行排列 然后再对第二列按照从小到大的顺序进行排列 ... 
- SSM框架—环境搭建(MyEclipse+Tomcat+MAVEN+SVN)
			1.JDK的安装 首先下载JDK,这个从sun公司官网可以下载,根据自己的系统选择64位还是32位,安装过程就是next一路到底.安装完成之后当然要配置环境变量了. 1.1新建变量名:JAVA_HOM ... 
- WebClient图片下载
			使用WebClient下载文件非常方便,针对有部分网站通过请求头的Referer,做了图片防盗链,可以在webClient加上Referer 来模拟请求 string basePath = Path. ... 
- vim 基础命令大全
			VIM命令大全 光标控制命令 命令 光标移动h 向左移一个字符j 向下移一行k ... 
- LeetCode算法题-Nth Digit(Java实现)
			这是悦乐书的第215次更新,第228篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第83题(顺位题号是400).找到无限整数序列的第n个数字1,2,3,4,5,6,7,8 ... 
- Metasploit渗透测试实际应用
			Metasploit:如何在 Metasploit 中使用反弹 Shell https://xz.aliyun.com/t/2380 Metasploit:如何使用 msfvenom https:// ... 
