当前位置: 首页 > news >正文

[luoguP3159] [CQOI2012]交换棋子(最小费用最大流)

传送门

 

好难的网络流啊,建图真的超难。

如果不告诉我是网络流的话,我估计就会写dfs了。

 

使用费用流解决本题,设点 $p[i][j]$ 的参与交换的次数上限为 $v[i][j]$ ,以下为建图方式:

  1. 将一个点分成三个点,分别为入点,原点和出点。

  2. 如果开始的图上该位置有棋子,那么从S到该点的原点连一条边权1,费用0的边

  3. 如果结束的图上该位置有棋子,那么从该点的原点到T连一条边权1,费用0的边

  4. 如果该点只在开始的图上出现,那么从该点的入点向原点连一条边权为 $v[i][j]/2$ ,费用为1的边,从该点的原点向出点连一条边权为 $(v[i][j]+1)/2$ ,费用为0的边

  5. 如果该点只在结束的图上出现,那么从该点的入点向原点连一条边权为 $(v[i][j]+1)/2$ ,费用为1的边,从该点的原点向出点连一条边权为 $v[i][j]/2$ ,费用为0的边

  6. 如果以上两点都不符合,那么从该点的入点向原点连一条边权为 $v[i][j]/2$ ,费用为1的边,从该点的原点向出点连一条边权为 $v[i][j]/2$ ,费用为0的边

——by zhouyonglong

我只是题解的搬运工。

最后把每个点的原点和它相邻的点的原点连一条容量为INF,费用为0的边

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1000001
#define id(i, j, k) ((i - 1) * m + j + (k - 1) * n * m)

using namespace std;

int n, m, cnt, s, t, ans, sum1, sum2, sum;
int head[N], to[N], nex[N], val[N], cost[N], dis[N], pre[N], path[N];
char s1[21][21], s2[21][21], c[21][21];
const int dx[8] = {1, 1, 0, -1, -1, -1, 0, 1}, dy[8] = {0, 1, 1, 1, 0, -1, -1, -1};
bool vis[N];

inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
	for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
	return x * f;
}

inline void add(int x, int y, int z, int v)
{
	to[cnt] = y;
	val[cnt] = z;
	cost[cnt] = v;
	nex[cnt] = head[x];
	head[x] = cnt++;
}

inline bool spfa()
{
	int i, u, v;
	queue <int> q;
	memset(vis, 0, sizeof(vis));
	memset(pre, -1, sizeof(pre));
	memset(dis, 127, sizeof(dis));
	q.push(s);
	dis[s] = 0;
	while(!q.empty())
	{
		u = q.front();
		vis[u] = 0;
		q.pop();
		for(i = head[u]; ~i; i = nex[i])
		{
			v = to[i];
			if(val[i] && dis[v] > dis[u] + cost[i])
			{
				dis[v] = dis[u] + cost[i];
				pre[v] = u;
				path[v] = i;
				if(!vis[v])
				{
					q.push(v);
					vis[v] = 1;
				}
			}
		}
	}
	return pre[t] != -1;
}

inline void E()
{
	puts("-1"), exit(0);
}

int main()
{
	int i, j, k, x, y, f;
	n = read();
	m = read();
	s = 0, t = 3 * n * m + 1;
	memset(head, -1, sizeof(head));
	for(i = 1; i <= n; i++) scanf("%s", s1[i] + 1);
	for(i = 1; i <= n; i++) scanf("%s", s2[i] + 1);
	for(i = 1; i <= n; i++) scanf("%s", c[i] + 1);
	for(i = 1; i <= n; i++)
		for(j = 1; j <= m; j++)
		{
			c[i][j] -= '0';
			if(s1[i][j] == '1')
			{
				sum1++;
				add(s, id(i, j, 2), 1, 0);
				add(id(i, j, 2), s, 0, 0);
			}
			if(s2[i][j] == '1')
			{
				sum2++;
				add(id(i, j, 2), t, 1, 0);
				add(t, id(i, j, 2), 0, 0);
			}
			if(s1[i][j] == '1' && s2[i][j] == '0')
			{
				add(id(i, j, 1), id(i, j, 2), c[i][j] / 2, 1);
				add(id(i, j, 2), id(i, j, 1), 0, -1);
				add(id(i, j, 2), id(i, j, 3), (c[i][j] + 1) / 2, 0);
				add(id(i, j, 3), id(i, j, 2), 0, 0);
			}
			if(s1[i][j] == '0' && s2[i][j] == '1')
			{
				add(id(i, j, 1), id(i, j, 2), (c[i][j] + 1) / 2, 1);
				add(id(i, j, 2), id(i, j, 1), 0, -1);
				add(id(i, j, 2), id(i, j, 3), c[i][j] / 2, 0);
				add(id(i, j, 3), id(i, j, 2), 0, 0);
			}
			if(s1[i][j] == s2[i][j])
			{
				add(id(i, j, 1), id(i, j, 2), c[i][j] / 2, 1);
				add(id(i, j, 2), id(i, j, 1), 0, -1);
				add(id(i, j, 2), id(i, j, 3), c[i][j] / 2, 0);
				add(id(i, j, 3), id(i, j, 2), 0, 0);
			}
			for(k = 0; k < 8; k++)
			{
				x = i + dx[k];
				y = j + dy[k];
				if(1 <= x && x <= n && 1 <= y && y <= m)
				{
					add(id(i, j, 3), id(x, y, 1), 1e9, 0);
					add(id(x, y, 1), id(i, j, 3), 0, 0);
				}
			}
		}
	if(sum1 != sum2) E();
	while(spfa())
	{
		f = 1e9;
		for(i = t; i != s; i = pre[i]) f = min(f, val[path[i]]);
		sum += f;
		ans += dis[t];
		for(i = t; i != s; i = pre[i])
		{
			val[path[i]] -= f;
			val[path[i] ^ 1] += f;
		}
	}
	if(sum != sum1) E();
	printf("%d\n", ans);
	return 0;
}

  

转载于:https://www.cnblogs.com/zhenghaotian/p/8249702.html

相关文章:

  • 网络舆情事件发展趋势变化监测分析的方法
  • saltstack安装与配置
  • 网络舆情信息工作怎么做的措施及建议
  • TCP、IP、ARP协议之间的工作关系
  • 网上社区舆情舆论信息有效监测的技术解决方法
  • 文本溢出(单行、多行)
  • 网络舆情数据分析系统技术方案
  • 数据库连接池
  • 网络舆情风险点排查工作实施方案
  • 使用Properties配置文件 InputStream与FileReader (java)
  • 网络舆情早发现预警的系统技术办法
  • java中的float和double的精度问题
  • 大数据舆情监测分析工作如何有效做好的解决方案
  • 网络舆情数据挖掘分析的三点方法和建议
  • python3----冒泡排序
  • [译]Python中的类属性与实例属性的区别
  • 2017年终总结、随想
  • exports和module.exports
  • JSONP原理
  • MySQL数据库运维之数据恢复
  • Python 基础起步 (十) 什么叫函数?
  • Vue 2.3、2.4 知识点小结
  • vue总结
  • webgl (原生)基础入门指南【一】
  • 初识 beanstalkd
  • 多线程事务回滚
  • 记一次和乔布斯合作最难忘的经历
  • 实现菜单下拉伸展折叠效果demo
  • 一个完整Java Web项目背后的密码
  • 终端用户监控:真实用户监控还是模拟监控?
  • 交换综合实验一
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • ${factoryList }后面有空格不影响
  • (09)Hive——CTE 公共表达式
  • (9)YOLO-Pose:使用对象关键点相似性损失增强多人姿态估计的增强版YOLO
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (转)EXC_BREAKPOINT僵尸错误
  • . Flume面试题
  • .net利用SQLBulkCopy进行数据库之间的大批量数据传递
  • @ModelAttribute 注解
  • @Pointcut 使用
  • @德人合科技——天锐绿盾 | 图纸加密软件有哪些功能呢?
  • [2018-01-08] Python强化周的第一天
  • [8-27]正则表达式、扩展表达式以及相关实战
  • [C++]STL之map
  • [C++]拼图游戏
  • [codeforces]Checkpoints
  • [Effective C++读书笔记]0012_复制对象时勿忘其每一部分
  • [Godot] 3D拾取
  • [Linux] CE知识随笔含Ansible、防火墙、VIM、其他服务
  • [Lucene] Lucene 全文检索引擎简介
  • [LVGL]:MACOS下使用LVGL模拟器