n,m<=20,给两个n×m布尔矩阵,每次操作可将第一个矩阵的2个相邻元素互换。输出最少操作次数使得两个矩阵完全一样。

比赛的时候想过按照二分图完美匹配的类似做法构图,不过想到边太多以及卡各种题卡得没脾气,就先放放等赛后搞了。。。

看题解发现有更好的构图,所以就算当时搞了也是TLE。。。。

先对所有格子及其上下左右连条流量为inf,费用为1的边,表示使用这条边每次是花费1个操作。

然后将第一个矩阵为1的点连S,流量为1,费用0,表示这个1可以用于满足第二个矩阵的某一个需要

第二个矩阵为1的点连T,流量为1,费用0,表示满足了这个1的需求

答案就是满流的最小费用了。。

以前都是用SPFA版本的,第一次用ZKW版本。。。

参考:

ZKW: http://www.artofproblemsolving.com/blog/54262

DMutehttp://blog.sina.com.cn/s/blog_76f6777d0101bbc8.html

这里算是把ZKW封装模板化,备用。。。

SPFA版本:1884ms

ZKW版本:276ms

ZKW使用的是选d[v]==d[u]+w(u,v)的思想

SPFA版本:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std; #define ll long long #define maxn 444
#define maxe 55000
#define inf 0x3f3f3f3f struct Edge{
int u, v, nxt, cap, cost;
}edge[maxe];
int head[maxn]; struct MinCostMaxFlow{
queue<int> que;
int add; // edges number
int vn; // total vertex number
int cost[maxn], in[maxn], pre[maxn];
bool vis[maxn];
void init(int sz){
add = 0; vn = sz + 10; memset(head, -1, sizeof(head));
while (!que.empty()) que.pop();
}
void insert(int u, int v, int w, int c){// u, v, capacity, cost
edge[add].u = u; edge[add].v = v; edge[add].cap = w; edge[add].cost = c;
edge[add].nxt = head[u]; head[u] = add++;
edge[add].u = v; edge[add].v = u; edge[add].cap = 0; edge[add].cost = -c;
edge[add].nxt = head[v]; head[v] = add++;
}
bool spfa(int s, int e){
memset(cost, 0x3f3f3f3f, sizeof(cost));
memset(in, 0, sizeof(in));
memset(vis, 0, sizeof(vis));
cost[s] = 0; pre[s] = -1;
que.push(s); vis[s] = true; in[s]++;
while (!que.empty()){
int u = que.front(); que.pop();
vis[u] = false;
for (int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].v;
if (edge[i].cap > 0 && cost[v] > cost[u] + edge[i].cost){
cost[v] = cost[u] + edge[i].cost; pre[v] = i;
if (!vis[v]){
que.push(v); vis[v] = true; in[v]++;
if (in[v] > vn) return false;
}
}
}
}
return cost[e] < inf;
}
void mincostmaxflow(int s, int e, int &mincost, int &maxflow){
mincost = 0, maxflow = 0;
while (spfa(s, e)){
int flow = inf;
for (int i = pre[e]; i != -1; i = pre[edge[i].u]){
flow = min(flow, edge[i].cap);
}
maxflow += flow;
for (int i = pre[e]; i != -1; i = pre[edge[i].u]){
edge[i].cap -= flow;
edge[i ^ 1].cap += flow;
}
mincost += cost[e] * flow;
}
}
}net; int a[22][22];
int b[22][22];
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) scanf("%d",a[i]+j);
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) scanf("%d",b[i]+j);
net.init(n*m+2);
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
for(int k=0;k<4;++k){
int ii=i+dx[k], jj=j+dy[k];
int u=(i-1)*m+j, v=(ii-1)*m+jj;
if(ii&&jj&&ii<=n&&jj<=m) net.insert(u,v,inf,1);
}
if(a[i][j]) net.insert(0,(i-1)*m+j,1,0);
if(b[i][j]) net.insert((i-1)*m+j,n*m+1,1,0);
}
}
int ans1=-1,ans2=-1;
net.mincostmaxflow(0,n*m+1,ans1,ans2);
printf("%d\n",ans1);
}
return 0;
}

ZKW:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std; #define maxn 410
#define maxm 510000
#define inf 0x3f3f3f3f struct Edge{
int u,v,nxt,cap,cost;
}edge[maxm];
int head[maxn]; struct ZKW_CostFlow{// 1-based
int S,T;
int add;// edges number
bool vis[maxn];
int dis[maxn], slk[maxn];
int ans;
void init(){ add=0; memset(head, -1, sizeof(head)); }
void insert(int u, int v, int w, int c){// u, v, capacity, cost
edge[add].u = u; edge[add].v = v; edge[add].cap = w; edge[add].cost = c;
edge[add].nxt = head[u]; head[u] = add++;
edge[add].u = v; edge[add].v = u; edge[add].cap = 0; edge[add].cost = -c;
edge[add].nxt = head[v]; head[v] = add++;
}
int aug(int u,int f){
int left=f;
if(u==T){ans+=f*dis[S];return f;}
vis[u]=true;
for(int i=head[u];i!=-1;i=edge[i].nxt){
int cap = edge[i].cap, v = edge[i].v;
if(cap>0 && vis[v]==false){
int t = dis[v] + edge[i].cost - dis[u];
if(t==0){
int delt = aug(v, cap<left?cap : left);
if(delt>0) edge[i].cap-=delt, edge[i^1].cap+=delt, left-=delt;
if(left==0) return f;
}else slk[v] = t<slk[v]?t:slk[v];
}
}
return f-left;
}
bool modlabel(int n){
int delt = inf;
for(int i=1;i<=n;++i)
if(!vis[i]) delt=min(delt,slk[i]), slk[i]=inf;
if(delt==inf) return true;
for(int i=1;i<=n;++i)
if(vis[i]) dis[i]+=delt;
return false;
}
void ZKW_Flow(int src,int des,int n,int& micost,int& maflow){
S=src, T=des;
ans=micost=maflow=0;
memset(dis,0,sizeof(dis));
memset(slk,0x3f,sizeof(slk));
do{
int tmp=0;
do{
memset(vis,false,sizeof(vis));
maflow+=tmp;
}while(tmp=aug(S,inf));
}while(!modlabel(n));
micost=ans;
}
}net;// 1-based int a[22][22];
int b[22][22];
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) scanf("%d",a[i]+j);
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) scanf("%d",b[i]+j);
net.init();
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
for(int k=0;k<4;++k){
int ii=i+dx[k], jj=j+dy[k];
int u=(i-1)*m+j, v=(ii-1)*m+jj;
if(ii&&jj&&ii<=n&&jj<=m) net.insert(u,v,inf,1);
}
if(a[i][j]) net.insert(n*m+1,(i-1)*m+j,1,0);
if(b[i][j]) net.insert((i-1)*m+j,n*m+2,1,0);
}
}
int ans1=-1,ans2=-1;
net.ZKW_Flow(n*m+1,n*m+2,n*m+2,ans1,ans2);
printf("%d\n",ans1);
}
return 0;
}

NSOJ A fairy tale of the two(最小费用最大流、SPFA版本、ZKW版本)的更多相关文章

  1. 最小费用最大流spfa

    #include <iostream> #include <cstring> #include <cstdio> #include <queue> #d ...

  2. P3381 【模板】最小费用最大流(spfa板子)

    #include<bits/stdc++.h> using namespace std; #define lowbit(x) ((x)&(-x)) typedef long lon ...

  3. Luogu--3381 【模板】最小费用最大流

    题目链接 3381 [模板]最小费用最大流 手写堆版本 dijkstra   400+ms 看来优先队列的常数好大 #include<bits/stdc++.h> using namesp ...

  4. [板子]最小费用最大流(Dijkstra增广)

    最小费用最大流板子,没有压行.利用重标号让边权非负,用Dijkstra进行增广,在理论和实际上都比SPFA增广快得多.教程略去.转载请随意. #include <cstdio> #incl ...

  5. bzoj1927最小费用最大流

    其实本来打算做最小费用最大流的题目前先来点模板题的,,,结果看到这道题二话不说(之前打太多了)敲了一个dinic,快写完了发现不对 我当时就这表情→   =_=你TM逗我 刚要删突然感觉dinic的模 ...

  6. ACM/ICPC 之 卡卡的矩阵旅行-最小费用最大流(可做模板)(POJ3422)

    将每个点拆分成原点A与伪点B,A->B有两条单向路(邻接表实现时需要建立一条反向的空边,并保证环路费用和为0),一条残留容量为1,费用为本身的负值(便于计算最短路),另一条残留容量+∞,费用为0 ...

  7. HDU5900 QSC and Master(区间DP + 最小费用最大流)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5900 Description Every school has some legends, ...

  8. P3381 【模板】最小费用最大流

    P3381 [模板]最小费用最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行 ...

  9. 【BZOJ-3876】支线剧情 有上下界的网络流(有下界有源有汇最小费用最大流)

    3876: [Ahoi2014]支线剧情 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 821  Solved: 502[Submit][Status ...

  10. hdu 4411 2012杭州赛区网络赛 最小费用最大流 ***

    题意: 有 n+1 个城市编号 0..n,有 m 条无向边,在 0 城市有个警察总部,最多可以派出 k 个逮捕队伍,在1..n 每个城市有一个犯罪团伙,          每个逮捕队伍在每个城市可以选 ...

随机推荐

  1. thinkphp 项目分组 -开发随笔1

    php中变量的声明, 和变量的初始化 是结合在一起的, 要声明变量, 就是通过初始化变量来实现的. 感觉页面版式的布局, 还是: 先大致规划出布局, 如两栏 三栏, 一览的左右上下结合, 搭配. 然后 ...

  2. Backbone事件模块源码分析

    事件模块Backbone.Events在Backbone中占有十分重要的位置,其他模块Model,Collection,View所有事件模块都依赖它.通过继承Events的方法来实现事件的管理,可以说 ...

  3. Ionic 常见问题及解决方案

    前言 Ionic是目前较为流行的Hybird App解决方案,在Ionic开发过程中会遇到很多常见的开发问题,本文尝试对这些问题给出解决方案. 一些常识与技巧 list 有延迟,可以在ion-cont ...

  4. 【活动】不用买书,不用花钱,可以免费看HTML5入门连载了

    清华大学出版社推出的<HTML 5网页开发实例详解>适合HTML 5开发初学者和前端开发工程师.本书一经上市,就获得了读者的一致好评,为感谢读者,推出本书的连载活动.   本书术新颖.与时 ...

  5. windows 下wamp环境2 配置之mysql的安装

    安装配置mysql 5.7 打开mysql官网: https://www.mysql.com/ 点击downloads,然后选择commuity 选择MySQL Community Server选择对 ...

  6. 15天学会jquery

    第二章 15 Days of jQuery 比window.onload 更快一些的载入 window.onload()是传统javascript 里一个能吃苦耐劳的家伙.它长久以来一直 被程序员们作 ...

  7. 深入理解Java虚拟机之读书笔记三 内存分配策略

    一般的内存分配是指堆上的分配,但也可能经过JIT编译后被拆散为标量类型并间接地在栈上分配.对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓冲,将按线程优先在TLAB上分配,少数情况下直接分 ...

  8. BZOJ3224——Tyvj 1728 普通平衡树

    1.题目大意:数据结构题,是treap,全都是treap比较基本的操作 2.分析:没啥思考的 #include <cstdio> #include <cstdlib> #inc ...

  9. BZOJ2809——[Apio2012]dispatching

    1.题目大意:给一棵树和M值,每个点有两个权值C和L,选x个点,这x个点的C值的和不能超过M,且这x个点如果都在某个子树内 定义满意度为x*这个子树的根的L值 2.分析:这是一道可并堆的题目,我们考虑 ...

  10. PC-BSD 换名 TrueOS

    导读 PC-BSD 重大更新:面向私人电脑的PC-BSD操作系统开发者.Lumina桌面环境创造者Ken Moore今天宣布系统迎来重大改变. 首先,PC-BSD更名为TrueOS,用户依然能够在PC ...