【Luogu】P3159交换棋子(超出我能力范围的费用流)
明显超出我能力范围。
只放题解。
再放代码。
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cctype>
#include<queue>
#define maxn 100200
using namespace std;
inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} int n,m;
inline int calc(int x,int y,int z){ return (x-)*m+y+(z-)*(n*m); }
inline int count(int i){ return i&?i+:i-; }
struct Edge{
int from,next,to,dis,val,flow;
}edge[maxn];
int head[maxn],num;
inline void addedge(int from,int to,int dis,int val){
edge[++num]=(Edge){from,head[from],to,dis,val,};
head[from]=num;
}
inline void add(int from,int to,int dis,int val){
addedge(from,to,dis,val);
addedge(to,from,-dis,);
} bool sta[][];
bool edn[][];
int swa[][];
int Start,End; int u[]={,,,,,,-,-,-};
int w[]={,,,,-,-,-,,}; struct Ans{
long long dis,val;
Ans(){dis=val=;}
}; long long dis[maxn];
long long pre[maxn];
int flow[maxn];
bool vis[maxn];
int sum; Ans spfa(){
Ans ans;
memset(dis,/,sizeof(dis)); long long Max=dis[];
dis[Start]=; flow[Start]=0x7fffffff;
queue<int>q; q.push(Start);
while(!q.empty()){
int from=q.front();q.pop();vis[from]=;
for(int i=head[from];i;i=edge[i].next){
int to=edge[i].to;
if(edge[i].dis+dis[from]>=dis[to]||edge[i].val==edge[i].flow) continue;
dis[to]=dis[from]+edge[i].dis;
pre[to]=i;
flow[to]=min(flow[from],edge[i].val-edge[i].flow);
if(!vis[to]){
vis[to]=;
q.push(to);
}
}
}
if(dis[End]==Max) return ans;
long long now=End; ans.val=flow[End]; ans.dis=dis[End];
sum+=flow[End];
while(now!=Start){
long long ret=pre[now];
edge[ret].flow+=flow[End];
edge[count(ret)].flow-=flow[End];
now=edge[ret].from;
}
return ans;
} int main(){
n=read(),m=read();
End=calc(n,m,)+;
for(int i=;i<=n;++i){
char ch[];
scanf("%s",ch+);
for(int j=;j<=m;++j) sta[i][j]=ch[j]-'';
}
for(int i=;i<=n;++i){
char ch[];
scanf("%s",ch+);
for(int j=;j<=m;++j) edn[i][j]=ch[j]-'';
}
for(int i=;i<=n;++i){
char ch[];
scanf("%s",ch+);
for(int j=;j<=m;++j) swa[i][j]=ch[j]-'';
}
int sum1=,sum2=;
for(int i=;i<=n;++i)
for(int j=;j<=m;++j){
if(sta[i][j]){
sum1++;
add(Start,calc(i,j,),,);
}
if(edn[i][j]){
sum2++;
add(calc(i,j,),End,,);
}
if(sta[i][j]&&(!edn[i][j])){
add(calc(i,j,),calc(i,j,),,swa[i][j]>>);
add(calc(i,j,),calc(i,j,),,(swa[i][j]+)>>);
}
if((!sta[i][j])&&edn[i][j]){
add(calc(i,j,),calc(i,j,),,(swa[i][j]+)>>);
add(calc(i,j,),calc(i,j,),,swa[i][j]>>);
}
if(sta[i][j]==edn[i][j]){
add(calc(i,j,),calc(i,j,),,swa[i][j]>>);
add(calc(i,j,),calc(i,j,),,swa[i][j]>>);
}
for(int k=;k<;++k){
int x=i+u[k];int y=j+w[k];
if(x<||x>n||y<||y>m) continue;
add(calc(i,j,),calc(x,y,),,0x7fffffff);
}
}
if(sum1!=sum2){
printf("-1");
return ;
}
int ans=;
while(){
Ans now=spfa();
if(!now.val) break;
ans+=now.val*now.dis;
}
if(sum!=sum1){
printf("-1");
return ;
}
printf("%d",ans);
return ;
}
https://www.luogu.org/problemnew/solution/P3159
【Luogu】P3159交换棋子(超出我能力范围的费用流)的更多相关文章
- 洛谷P3159 交换棋子 神奇的网络流
神奇的建模...原题链接 如果你真的把交换看成交换,就\(GG\)了.首先我们要把交换看成是白棋的移动. 然后,很容易的就想到建模的大致思路:建立超级源点S和超级汇点T,从S向初始局面每个白棋所在的格 ...
- 洛谷 P3159(BZOJ 2668)[CQOI2012]交换棋子
有一个\(n\)行\(m\)列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第\(i\)行第\(j\)列的格子只能参与\(m[i][j]\)次交换 ...
- P3159 [CQOI2012]交换棋子
思路 相当神奇的费用流拆点模型 最开始我想到把交换黑色棋子看成一个流流动的过程,流从一个节点流向另一个节点就是交换两个节点,然后把一个位置拆成两个点限制流量,然后就有了这样的建图方法 S向所有初始是黑 ...
- 【BZOJ-2668】交换棋子 最小费用最大流
2668: [cqoi2012]交换棋子 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1055 Solved: 388[Submit][Status ...
- BZOJ2668: [cqoi2012]交换棋子
题解: 可以戳这里:http://www.cnblogs.com/zig-zag/archive/2013/04/21/3033485.html 其实自己yy一下就知道这样建图的正确性了. 感觉太神奇 ...
- BZOJ 2668: [cqoi2012]交换棋子
2668: [cqoi2012]交换棋子 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1112 Solved: 409[Submit][Status ...
- 【BZOJ2668】[cqoi2012]交换棋子 费用流
[BZOJ2668][cqoi2012]交换棋子 Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列 ...
- BZOJ2668:[CQOI2012]交换棋子(费用流)
题目描述 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列的格子只能参与mi,j次交换. 输入输出格式 输入格式: 第一行 ...
- [cqoi2012]交换棋子
2668: [cqoi2012]交换棋子 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1334 Solved: 518[Submit][Stat ...
随机推荐
- POJ 4020 NEERC John's inversion 贪心+归并求逆序对
题意:给你n张卡,每张卡上有蓝色和红色的两种数字,求一种排列使得对应颜色数字之间形成的逆序对总数最小 题解:贪心,先按蓝色排序,数字相同再按红色排,那么蓝色数字的逆序总数为0,考虑交换红色的数字消除逆 ...
- UVA 12905 Volume of Revolution (几何,微积分)
题意:分段用椎台面积近似计算体积,然后计算出近似值和真实值的相对误差 微积分加数学. 平头椎台的体积计算公式: V = 1/3*h*(S1+S2*sqrt(S1*S2) 一个更快的计算多项式值的方法: ...
- Meaningful Mean
You are given an integer sequence of length N, a= {a1,a2,…,aN}, and an integer K.a has N(N+1)⁄2 non- ...
- ctrl+shift+f
ctrl+f是在当前文件寻找某个参数 ctrl+shift+f是在整个工程目录下寻找某个参数
- centos7 python3 Saltstack配置
Python安装完毕后,提示找不到ssl模块 pip is configured with locations that require TLS/SSL, however the ssl module ...
- 动态代理--Cglib
JDK 的Proxy 实现,需要代理对象实现接口: package com.utils; import java.lang.reflect.InvocationHandler; import java ...
- 通过脚本批量添加AD用户
1.新建一个csv文件(逗号分隔的一种值文件) 内容为:放在C:\盘根目录下 test300 test300 .com test300 test301 test301 .com test301 tes ...
- 01_6_SERVLET如何从上一个页面取得参数
01_6_SERVLET如何从上一个页面取得参数 1. sevlet实现 public void doGet(HttpServletRequest request, HttpServletRespon ...
- Ubuntu下删除mysql数据库
Ubuntu下删除mysql数据库 sudo apt-get autoremove --purge mysql-server-5.7 sudo apt-get remove mysql-server ...
- Linux菜鸟起飞之路【六】权限管理(二)
一.权限信息详解 ls -l 文件 //查看文件权限写法1 ll 文件 //查看文件权限写法2 ls -dl 目录 //查看目录权限写法1 ll -d 目录 //查看目录权限写法2 文件权限格式: ...