前置姿势

\(k\)维空间内两点曼哈顿距离中绝对值的处理

戳这里:[CF1093G]Multidimensional Queries

多路增广的费用流

据说这个东西叫做ZKW费用流?

流程其实很简单,就是把EK中的单路回溯改成利用DFS多路增广,类似Dinic那样,可以看作是EK的一个优化。需要注意的是要标记从源点到当前点的路径,以免陷入零环无法自拔。

代码

bool spfa(){
memset(dis,0x3f,sizeof dis);
rin(i,1,n)cur[i]=head[i];
while(!q.empty())q.pop();
dis[s]=0,book[s]=true;q.push(s);
while(!q.empty()){
int x=q.front();q.pop();
trav(i,x){
int ver=e[i].to;
if(e[i].cap&&dis[ver]>dis[x]+e[i].cost){
dis[ver]=dis[x]+e[i].cost;
if(!book[ver]){
book[ver]=true;
q.push(ver);
}
}
}
book[x]=false;
}
return dis[t]<1e9;
} int dfs(int x,int pref){
if(x==t||!pref)return pref;
int temp=0,flow=0;insta[x]=true;
for(int &i=cur[x];i;i=e[i].nxt){
int ver=e[i].to;if(insta[ver])continue;
if(dis[ver]==dis[x]+e[i].cost&&(temp=dfs(ver,std::min(pref,e[i].cap)))){
e[i].cap-=temp;
e[i^1].cap+=temp;
flow+=temp;
pref-=temp;
mincost+=temp*e[i].cost;
if(!pref)break;
}
}
insta[x]=false;
return flow;
} void ek(){
while(spfa())maxflow+=dfs(s,1e9);
}

分析

显然费用流,直接建图的话每一对红球和蓝球(的位置)都需要连边,一共要连\(O(N^2)\)条边,再跑费用流的话显然时间爆炸。

注意到把绝对值拆开后\((x,y)\)系数只有\(2^2\)种可能性,并且两个球的距离是这四种情况中最大值,所以我们可以对四种情况分开处理,因为我们知道一对匹配的费用取的一定是最大值,即这两个球的距离。

具体如何建图可以参考代码。

代码

#include <bits/stdc++.h>

#define rin(i,a,b) for(int i=(a);i<=(b);++i)
#define irin(i,a,b) for(int i=(a);i>=(b);--i)
#define trav(i,a) for(int i=head[a];i;i=e[i].nxt)
#define Size(a) (int)a.size()
#define pb push_back
#define mkpr std::make_pair
#define fi first
#define se second
#define lowbit(a) ((a)&(-(a)))
typedef long long LL; using std::cerr;
using std::endl; inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*f;
} const int MAXN=1005; int n,s,t,ecnt=1,head[MAXN<<1]; struct Edge{
int to,nxt,cap,cost;
}e[MAXN*20]; inline void add_edge(int bg,int ed,int ca,int co){
++ecnt;
e[ecnt].to=ed;
e[ecnt].nxt=head[bg];
e[ecnt].cap=ca;
e[ecnt].cost=co;
head[bg]=ecnt;
} int maxflow,cur[MAXN<<1];
LL mincost,dis[MAXN<<1];
bool book[MAXN<<1],insta[MAXN<<1];
std::queue<int> q; bool spfa(){
memset(dis,0x3f,sizeof dis);
rin(i,1,t)cur[i]=head[i];
while(!q.empty())q.pop();
dis[s]=0,book[s]=true;q.push(s);
while(!q.empty()){
int x=q.front();q.pop();
trav(i,x){
int ver=e[i].to;
if(e[i].cap&&dis[ver]>dis[x]+e[i].cost){
dis[ver]=dis[x]+e[i].cost;
if(!book[ver]){
book[ver]=true;
q.push(ver);
}
}
}
book[x]=false;
}
return dis[t]<1e18;
} int dfs(int x,int pref){
if(x==t||!pref)return pref;
int temp=0,flow=0;insta[x]=true;
for(int &i=cur[x];i;i=e[i].nxt){
int ver=e[i].to;if(insta[ver])continue;
if(dis[ver]==dis[x]+e[i].cost&&(temp=dfs(ver,std::min(pref,e[i].cap)))){
e[i].cap-=temp;
e[i^1].cap+=temp;
flow+=temp;
pref-=temp;
mincost+=1ll*temp*e[i].cost;
if(!pref)break;
}
}
insta[x]=false;
return flow;
} void ek(){
while(spfa())maxflow+=dfs(s,1e9);
} int main(){
n=read();
int x0=n*2+1,x1=x0+1,x2=x1+1,x3=x2+1;
s=x3+1,t=s+1;
rin(i,1,n){
int rx=read(),ry=read(),rc=read();
add_edge(s,i,rc,0);
add_edge(i,s,0,0);
add_edge(i,x0,1e9,rx+ry);
add_edge(x0,i,0,-rx-ry);
add_edge(i,x1,1e9,rx-ry);
add_edge(x1,i,0,-rx+ry);
add_edge(i,x2,1e9,-rx+ry);
add_edge(x2,i,0,rx-ry);
add_edge(i,x3,1e9,-rx-ry);
add_edge(x3,i,0,rx+ry);
}
rin(i,1,n){
int bx=read(),by=read(),bc=read();
add_edge(n+i,t,bc,0);
add_edge(t,n+i,0,0);
add_edge(x0,n+i,1e9,-bx-by);
add_edge(n+i,x0,0,bx+by);
add_edge(x1,n+i,1e9,-bx+by);
add_edge(n+i,x1,0,bx-by);
add_edge(x2,n+i,1e9,bx-by);
add_edge(n+i,x2,0,-bx+by);
add_edge(x3,n+i,1e9,bx+by);
add_edge(n+i,x3,0,-bx-by);
}
ek();
printf("%lld\n",-mincost);
return 0;
}

[AGC034D]Manhattan Max Matching:费用流的更多相关文章

  1. 【杂题】[AGC034D] Manhattan Max Matching【费用流】

    Description 有一个无限大的平面,有2N个位置上面有若干个球(可能重复),其中N个位置是红球,N个位置是蓝球,红球与蓝球的总数均为S. 给出2N个位置和上面的球数,现要将红球与蓝球完美匹配, ...

  2. @atcoder - AGC034D@ Manhattan Max Matching

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 考虑一个二维平面,执行共 2*N 次操作: 前 N 次,第 i ...

  3. 「AGC034D」 Manhattan Max Matching

    「AGC034D」 Manhattan Max Matching 传送门 不知道这个结论啊... (其实就是菜嘛) 首先 \(O(n^2)\) 的建边显然不太行. 曼哈顿距离有这样一个性质,如果将绝对 ...

  4. [2019多校联考(Round 6 T3)]脱单计划 (费用流)

    [2019多校联考(Round 6 T3)]脱单计划 (费用流) 题面 你是一家相亲机构的策划总监,在一次相亲活动中,有 n 个小区的若干男士和 n个小区的若干女士报名了这次活动,你需要将这些参与者两 ...

  5. BZOJ3130: [Sdoi2013]费用流[最大流 实数二分]

    3130: [Sdoi2013]费用流 Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 960  Solved: 5 ...

  6. 洛谷 1004 dp或最大费用流

    思路: dp方法: 设dp[i][j][k][l]为两条没有交叉的路径分别走到(i,j)和(k,l)处最大价值. 则转移方程为 dp[i][j][k][l]=max(dp[i-1][j][k-1][l ...

  7. bzoj4514: [Sdoi2016]数字配对--费用流

    看了一眼题目&数据范围,觉得应该是带下界的费用流 原来想拆点变成二分图,能配对的连边,跑二分图,可行性未知 后来看到另外一种解法.. 符合匹配要求的数要满足:质因子的个数相差为1,且两者可整除 ...

  8. BZOJ-3130 费用流 (听题目胡扯丶裸最大流) 二分判定+最大流+实数精度乱搞

    DCrusher爷喜欢A我做的水题,没办法,只能A他做不动的题了.... 3130: [Sdoi2013]费用流 Time Limit: 10 Sec Memory Limit: 128 MBSec ...

  9. 【TYVJ】1982 武器分配(费用流)

    http://tyvj.cn/Problem_Show.aspx?id=1982 一眼题.. 源向每个人连容量为1,费用为0的边. 每个人向一个中转节点na连容量1,费用0的边(你也可以不连,直接连后 ...

随机推荐

  1. 初入JavaWeb(半成品)

    2019-10-21 20:51:03 初次进行Javaweb的开发. 要求: 1登录账号:要求由6到12位字母.数字.下划线组成,只有字母可以开头:(1分) 2登录密码:要求显示“• ”或“*”表示 ...

  2. nginx配置ssi实现页面拆分

    在做一个网站时,页面上会有很多重复的内容,每个页面写一遍很冗余,修改时还容易遗漏,所以可以把公共的部分写好,放在单独的HTML中,用时引用就行了. nginx配置ssi可以将单个页面拆分成一个一个的小 ...

  3. Python sqlalchemy 高级用法

    一. 关联查询 sys_user_list = SysPermission.query.join(OrgRolePermission, OrgRolePermission.sys_permission ...

  4. C语言函数调用时候内存中栈的动态变化详细分析(彩图)

    版权声明:本文为博主原创文章,未经博主允许不得转载.欢迎联系我qq2488890051 https://blog.csdn.net/kangkanglhb88008/article/details/8 ...

  5. python+minicap的使用

    说起Minicap,不得不提到STF,STF (Smartphone Test Farm) 是一个开源的web架构应用,用户可通过浏览器远程操作Android设备.调试Android应用.在设备上进行 ...

  6. 关于redis的几件小事(八)缓存与数据库双写时的数据一致性

    1.Cache aside pattern 这是最经典的 缓存+数据库 读写模式,操作如下: ①读的时候,先读缓存,缓存没有就读数据库,然后将取出的数据放到缓存,同时返回请求响应. ②更新的时候,先删 ...

  7. Scala新版本学习(2):

    1.本章要点; (1)if表达式有值: (2)块也有值,是它最后一个表达式的值 (3)Scala的for循环就像是"增强版的"Java for循环 (4)分号不是必须的 (5)vo ...

  8. 使用python进行pdf文件分割

    Python代码 import os from pyPdf import PdfFileWriter, PdfFileReader def split(pdf_file, delta, output_ ...

  9. 01 Linux常用基本命令(一)

    1.远程连接服务器 Xshell为例: ssh 用户名@IP地址 (ssh root@192.168.119.139) 查看服务器的IP地址: ifconfig (ip addr) 2.命令 1.ls ...

  10. Python 第一个程序

    第一个程序 打开pycharm,新建一个工程,新建一个文件(后缀为.py) 书写最简单的代码:print(人生苦短,我用python!) 执行python代码 使用pycharm的运行按钮 终端下输入 ...