题目链接

  明显超出我能力范围。

  只放题解

  再放代码。

#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交换棋子(超出我能力范围的费用流)的更多相关文章

  1. 洛谷P3159 交换棋子 神奇的网络流

    神奇的建模...原题链接 如果你真的把交换看成交换,就\(GG\)了.首先我们要把交换看成是白棋的移动. 然后,很容易的就想到建模的大致思路:建立超级源点S和超级汇点T,从S向初始局面每个白棋所在的格 ...

  2. 洛谷 P3159(BZOJ 2668)[CQOI2012]交换棋子

    有一个\(n\)行\(m\)列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第\(i\)行第\(j\)列的格子只能参与\(m[i][j]\)次交换 ...

  3. P3159 [CQOI2012]交换棋子

    思路 相当神奇的费用流拆点模型 最开始我想到把交换黑色棋子看成一个流流动的过程,流从一个节点流向另一个节点就是交换两个节点,然后把一个位置拆成两个点限制流量,然后就有了这样的建图方法 S向所有初始是黑 ...

  4. 【BZOJ-2668】交换棋子 最小费用最大流

    2668: [cqoi2012]交换棋子 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1055  Solved: 388[Submit][Status ...

  5. BZOJ2668: [cqoi2012]交换棋子

    题解: 可以戳这里:http://www.cnblogs.com/zig-zag/archive/2013/04/21/3033485.html 其实自己yy一下就知道这样建图的正确性了. 感觉太神奇 ...

  6. BZOJ 2668: [cqoi2012]交换棋子

    2668: [cqoi2012]交换棋子 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1112  Solved: 409[Submit][Status ...

  7. 【BZOJ2668】[cqoi2012]交换棋子 费用流

    [BZOJ2668][cqoi2012]交换棋子 Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列 ...

  8. BZOJ2668:[CQOI2012]交换棋子(费用流)

    题目描述 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列的格子只能参与mi,j次交换. 输入输出格式 输入格式: 第一行 ...

  9. [cqoi2012]交换棋子

      2668: [cqoi2012]交换棋子 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1334  Solved: 518[Submit][Stat ...

随机推荐

  1. [VC]WindowProc和DefWindowProc函数

    在Windows操作系统里,当窗口显示之后,它就可以接收到系统源源不断地发过来的消息,然后窗口就需要处理这些消息,因此就需要一个函数来处理这些消 息.在API里定义了一个函数为回调函数,当系统需要向窗 ...

  2. Python-DDT实现接口自动化

    Get请求参数化例子 import unittest import requests import ddt @ddt.ddt class MyTestCase(unittest.TestCase): ...

  3. 直接用bcdedit创建bootmgr数据库和修复启动菜单

    直接用bcdedit创建bootmgr数据库和修复启动菜单 使用下面方法之前需要bcdedit和bootsect两条命令,这两条命令可以到vista或者windows 7安装光盘上获得.bootsec ...

  4. redis cluster 配置

    #服务器192.168.56.111 192.168.56.112 192.168.56.113 计划1主2从   192.168.56.111 192.168.56.112 192.168.56.1 ...

  5. 微软与百度合作:win10搜索引擎默认百度

    全球最大的中文搜索引擎百度公司与微软公司共同宣布双方展开战略合作.百度并将成为中国市场上Windows 10 Microsoft Edge浏览器的默认主页和搜索引擎.也就是说,将来人们在win10的M ...

  6. Linux中断体系结构

    1.中断处理体系结构 Linux内核将所有中断统一编号,使用一个irq_desc结构数组来描述这些中断. 数组声明在/linux/kernel/irq/handle.c中,其中#define NR_I ...

  7. LeetCode(122) Best Time to Buy and Sell Stock II

    题目 Say you have an array for which the ith element is the price of a given stock on day i. Design an ...

  8. PAT Basic 1073

    1073 多选题常见计分法 批改多选题是比较麻烦的事情,有很多不同的计分方法.有一种最常见的计分方法是:如果考生选择了部分正确选项,并且没有选择任何错误选项,则得到 50% 分数:如果考生选择了任何一 ...

  9. 【草稿】JS中如何操作时间

    如何声明时间变量 如何设置时间变量的时.分.秒.毫秒 如何根据字符串变量,声明指定的时间变量 如何比较两个时间变量 代码如下: $(function () { var d = new Date(); ...

  10. 笔记-python-*号解包

    笔记-python-*号解包 在码代码时发现*号可以这样使用: str = ["abcd", "abce", "abcf"]st = &qu ...