【题解】CQOI2012交换棋子
感受到网络流的强大了……这道题目的关键在于:
前后颜色不变的,流入流出的次数相等;原本是黑色的最后变成了白色,流出比流入次数多1;原本是白色最后变成黑色,流入比流出次数多一。所以我们将每一点拆成3个点,分别代表流入点,原点与流出点。最开始为黑色的点与源点连流量为1,费用为0的边,最后为黑色的点与汇点连流量为1,费用为0的边。
#include<bits/stdc++.h>
using namespace std;
#define maxn 300
#define maxm 8000
#define INF 99999
int n, m, size, tem, a[maxn][maxn], b[maxn][maxn], c[maxn][maxn], head[maxm];
int cnp, fans, ans, cost, dis[maxm], pre[maxm], flow[maxm];
int dx[] = {, , , , , , -, -, -};
int dy[] = {, , -, , , -, , , -};
int s = , t;
bool vis[maxm];
deque <int> q; struct edge
{
int to, last, f, c;
}E[maxn * ]; void add(int u, int v, int f, int c)
{
E[cnp].to = v, E[cnp].last = head[u], E[cnp].f = f, E[cnp].c = c; head[u] = cnp ++;
E[cnp].to = u, E[cnp].last = head[v], E[cnp].f = , E[cnp].c = -c; head[v] = cnp ++;
} int Get_id(int x, int y)
{
return (x - ) * m + y;
} void init()
{
memset(head, -, sizeof(head));
} int SPFA()
{
q.push_back(s);
flow[s] = INF;
for(int i = ; i <= n * m * + ; i ++) dis[i] = INF;
while(!q.empty())
{
int u = q.front();
q.pop_front();
vis[u] = false;
for(int i = head[u]; i != -; i = E[i].last)
{
int v = E[i].to;
if(E[i].f && dis[v] > dis[u] + E[i].c)
{
dis[v] = dis[u] + E[i].c, pre[v] = i;
flow[v] = min(flow[u], E[i].f);
if(!vis[v])
{
vis[v] = true;
if(!q.empty() && dis[v] < dis[q.front()]) q.push_front(v);
else q.push_front(v);
}
}
}
}
if(dis[t] >= INF) return false;
else return true;
} void Max_flow()
{
while(SPFA())
{
int v = pre[t];
while()
{
E[v].f -= flow[t];
E[v ^ ].f += flow[t];
if(E[v ^ ].to == s) break;
v = pre[E[v ^ ].to];
}
ans += flow[t];
cost += flow[t] * dis[t];
}
} void Get_input()
{
for(int i = ; i <= n; i ++)
{
string s; cin >> s;
for(int j = ; j < m; j ++)
a[i][j + ] = s[j] - '';
}
for(int i = ; i <= n; i ++)
{
string s; cin >> s;
for(int j = ; j < m; j ++)
b[i][j + ] = s[j] - '';
}
for(int i = ; i <= n; i ++)
{
string s; cin >> s;
for(int j = ; j < m; j ++)
c[i][j + ] = s[j] - '';
}
} void Connect()
{
for(int i = ; i <= n; i ++)
for(int j = ; j <= m; j ++)
{
int u = Get_id(i, j);
if(a[i][j]) tem ++, add(s, u, , );
if(b[i][j]) fans ++, add(u, t, , );
if(a[i][j] == b[i][j])
{
add(u + size, u, c[i][j] / , );
add(u, u + * size, c[i][j] / , );
}
else if(b[i][j])
{
add(u + size, u, (c[i][j] + ) / , );
add(u, u + * size, c[i][j] / , );
}
else if(a[i][j])
{
add(u + size, u, c[i][j] / , );
add(u, u + * size, (c[i][j] + ) / , );
}
for(int k = ; k <= ; k ++)
{
int x = i + dx[k], y = j + dy[k];
if(x < || x > n || y < || y > m) continue;
add(u + * size, Get_id(x, y) + size, INF, );
}
}
} int main()
{
scanf("%d%d", &n, &m);
init();
t = n * m * + , size = n * m;
Get_input();
Connect();
if(tem != fans)
{
printf("-1\n");
return ;
}
Max_flow();
if(ans == fans) printf("%d", cost >> );
else printf("-1\n");
return ;
}
【题解】CQOI2012交换棋子的更多相关文章
- BZOJ2668: [cqoi2012]交换棋子
题解: 可以戳这里:http://www.cnblogs.com/zig-zag/archive/2013/04/21/3033485.html 其实自己yy一下就知道这样建图的正确性了. 感觉太神奇 ...
- 【BZOJ2668】[cqoi2012]交换棋子 费用流
[BZOJ2668][cqoi2012]交换棋子 Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列 ...
- BZOJ 2668: [cqoi2012]交换棋子
2668: [cqoi2012]交换棋子 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1112 Solved: 409[Submit][Status ...
- [cqoi2012]交换棋子
2668: [cqoi2012]交换棋子 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1334 Solved: 518[Submit][Stat ...
- BZOJ2668:[CQOI2012]交换棋子——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2668 https://www.luogu.org/problemnew/show/P3159#sub ...
- 洛谷 P3159(BZOJ 2668)[CQOI2012]交换棋子
有一个\(n\)行\(m\)列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第\(i\)行第\(j\)列的格子只能参与\(m[i][j]\)次交换 ...
- [CQOI2012]交换棋子 网络流
---题面--- 题解: 一开始很快想出了一个接近正解的建图方法,但其实是错误的,不过还是骗了70分_(:зゝ∠)_ 首先我们可以观察到棋子有限,但费用多种,其实也就相当于限制了流量,找最小费用 对于 ...
- BZOJ2668:[CQOI2012]交换棋子(费用流)
题目描述 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列的格子只能参与mi,j次交换. 输入输出格式 输入格式: 第一行 ...
- [luoguP3159] [CQOI2012]交换棋子(最小费用最大流)
传送门 好难的网络流啊,建图真的超难. 如果不告诉我是网络流的话,我估计就会写dfs了. 使用费用流解决本题,设点 $p[i][j]$ 的参与交换的次数上限为 $v[i][j]$ ,以下为建图方式: ...
随机推荐
- Hadoop(21)-数据清洗(ELT)简单版
有一个诸如这样的log日志 去除长度不合法,并且状态码不正确的记录 LogBean package com.nty.elt; /** * author nty * date time 2018-12- ...
- windows环境下安装scrapy框架报错问题--最快捷有效的解决方案
windows在执行如下命令,安装scrapy的过程中会报错: pip install scrapy 报错分析: windows环境下,会出现如下错误: 1.提示的错误是编译环境的问题,字面意思看需要 ...
- 015---Django的forms组件
Django form表单 Form介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用 ...
- go学习笔记-语言基础
语言基础 结构 基础组成: 包声明 引入包 函数 变量 语句 & 表达式 注释 程序 在开始编写应用之前,我们先从最基本的程序开始,在学习大部分语言之前,都会编写一个可以输出hello wor ...
- (数据科学学习手札24)逻辑回归分类器原理详解&Python与R实现
一.简介 逻辑回归(Logistic Regression),与它的名字恰恰相反,它是一个分类器而非回归方法,在一些文献里它也被称为logit回归.最大熵分类器(MaxEnt).对数线性分类器等:我们 ...
- R语言学习笔记(十七):data.table包中melt与dcast函数的使用
melt函数可以将宽数据转化为长数据 dcast函数可以将长数据转化为宽数据 > DT = fread("melt_default.csv") > DT family_ ...
- LeetCode算法1—— 两数之和
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 示例: 给定 nums = [2, 7, 11, 15], target ...
- [答网友问]让GridLength支持动画
原文:[答网友问]让GridLength支持动画 [答网友问]WPF中让GridLength类型支持动画 ...
- Mac OS下搭建Hadoop + Spark集群
首先注意版本兼容问题!!!本文采用的是Scala 2.11.8 + Hadoop 2.7.5 + Spark 2.2.0 请在下载Spark时务必看清对应的Scala和Hadoop版本! 一.配置JD ...
- Jexus支持HTTPS协议
众所周知,在HTTPS页面请求HTTP资料的时候,现代浏览器会拦截,提示用户是否继续,或者直接拦截,提示都不出来. 最近给自己做了个快速书签工具,点击书签就直接把书签发送到服务器地址,然后保存到我的网 ...