Description

有一个无限大的平面,有2N个位置上面有若干个球(可能重复),其中N个位置是红球,N个位置是蓝球,红球与蓝球的总数均为S。

给出2N个位置和上面的球数,现要将红球与蓝球完美匹配,匹配的权值是每一对匹配两个球的位置坐标的曼哈顿距离之和。

求最大权值。

N<=1000,每个位置上球数<=10,坐标非负且<=10^9

Solution

直接两两连边显然不行

但又不能对于每一个球单独计算贡献,因为绝对值的存在

考虑这样一个转化

|x1-x2|=max(x1-x2,x2-x1)

|x1-x2|+|y1-y2|=max(x1-x2+y1-y2,x2-x1+y1-y2,x1-x2+y2-y1,x2-x1+y2-y1)

我们额外建4个中转点表示上面的四种情况,红球和蓝球通过中转点连边,这样边数降到了O(N)

边权就按照上面四种情况的符号连,容量为1,跑最大费用最大流。

由于最大费用最大流的性质,保证了每个匹配都是最大的,因此恰好就是曼哈顿距离取了绝对值符号后的结果。

时间复杂度O(maxflow(N))

Code

#include <bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
const int N=2115;
const int INF=1e7;
typedef long long LL;
using namespace std;
vector <int> ap[N];
int n,n1,st,ed,f[N][N];
LL ans,pr[N][N];
void link(int x,int y,int w,LL c)
{
ap[x].push_back(y);
f[x][y]=w,pr[x][y]=c;
ap[y].push_back(x);
f[y][x]=0,pr[y][x]=-c;
}
typedef vector<int>::iterator IT;
namespace Flow
{
LL dis[N];
bool bz[N];
IT cur[N];
int d[200*N];
bool spfa()
{
memset(dis,107,sizeof(dis));
memset(bz,0,sizeof(bz));
dis[st]=0,bz[st]=1,d[1]=st;
fo(i,1,n1) cur[i]=ap[i].begin();
int l=0,r=1;
while(l<r)
{
int k=d[++l];
for(IT i=ap[k].begin();i!=ap[k].end();i++)
{
int p=*i;
if(f[k][p]&&dis[k]+pr[k][p]<dis[p])
{
dis[p]=dis[k]+pr[k][p];
if(!bz[p]) bz[p]=1,d[++r]=p;
}
}
bz[k]=0;
}
return (dis[ed]<=1e17);
}
int flow(int k,int s)
{
if(k==ed) return s;
int sl=0,v;
bz[k]=1;
for(;cur[k]!=ap[k].end();cur[k]++)
{
int p=*cur[k];
if(!bz[p]&&f[k][p]&&dis[p]==dis[k]+pr[k][p])
{
if(v=flow(p,min(s,f[k][p])))
{
sl+=v,s-=v;
f[k][p]-=v,f[p][k]+=v;
ans+=(LL)v*pr[k][p];
if(!s) break;
}
}
}
bz[k]=0;
return sl;
}
}
using Flow::flow;
using Flow::spfa;
int main()
{
cin>>n;
n1=2*n+6,st=2*n+5,ed=n1;
fo(i,1,n)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
link(st,i,z,0);
link(i,2*n+1,z,x+y);
link(i,2*n+2,z,x-y);
link(i,2*n+3,z,-x+y);
link(i,2*n+4,z,-x-y);
}
fo(i,1,n)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
link(i+n,ed,z,0);
link(2*n+1,i+n,z,-x-y);
link(2*n+2,i+n,z,-x+y);
link(2*n+3,i+n,z,x-y);
link(2*n+4,i+n,z,x+y);
}
ans=0;
while(spfa())
flow(st,INF);
printf("%lld\n",-ans);
}

【杂题】[AGC034D] Manhattan Max Matching【费用流】的更多相关文章

  1. [AGC034D]Manhattan Max Matching:费用流

    前置姿势 \(k\)维空间内两点曼哈顿距离中绝对值的处理 戳这里:[CF1093G]Multidimensional Queries 多路增广的费用流 据说这个东西叫做ZKW费用流? 流程其实很简单, ...

  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. 2018.10.15 loj#6010. 「网络流 24 题」数字梯形(费用流)

    传送门 费用流经典题. 按照题目要求建边. 为了方便我将所有格子拆点,三种情况下容量分别为111,infinfinf,infinfinf,费用都为validi,jval_{id_{i,j}}valid ...

  5. 2018.10.15 loj#6013. 「网络流 24 题」负载平衡(费用流)

    传送门 费用流sb题. 直接从sss向每个点连边,容量为现有物品量. 然后从ttt向每个点连边,容量为最后库存量. 由于两个点之间可以互相任意运送物品,因此相邻的直接连infinfinf的边就行了. ...

  6. 【Codevs1237&网络流24题餐巾计划】(费用流)

    题意:一个餐厅在相继的 N 天里,每天需用的餐巾数不尽相同. 假设第 i 天需要 ri块餐巾(i=1,2,…,N).餐厅可以购买新的餐巾,每块餐巾的费用为 p 分: 或者把旧餐巾送到快洗部,洗一块需 ...

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

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

  8. CF 277E Binary Tree on Plane (拆点 + 费用流) (KM也可做)

    题目大意: 平面上有n个点,两两不同.现在给出二叉树的定义,要求树边一定是从上指向下,即从y坐标大的点指向小的点,并且每个结点至多有两个儿子.现在让你求给出的这些点是否能构成一棵二叉树,如果能,使二叉 ...

  9. [NOI2012]美食节(费用流)

    题目描述 CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的美食.然而,尝鲜的欲望是难以满足的.尽管所有的菜品都 ...

随机推荐

  1. selenium Grid2环境搭建和基本使用

    Selenium Grid简介 利用Selenium Grid可以使主节点(hub)的测试用例在不同主机即分支点(node)运行.可以使一份测试用例在不同环境下(操作系统.浏览器)执行自动化测试.Se ...

  2. 完全删除MySQL及相关软件

    一.删除mysql服务 个人认为首先删除mysql服务最重要,这个多数人会忘记如何删除 首先是查看自己的mysql服务名,需要用这个服务名进行删除 进入命令行 二.卸载mysql,workbench等 ...

  3. Jconsole与Jmx 分析JVM状况(下) 转

    出处: Jconsole与Jmx 分析JVM状况(下) 线程(ThreadMXBean ) 从 Jconsole 画面取得线程画面如下: 左下角列出了所以正在运行的线程.通过点击某个线程,右下脚可以看 ...

  4. python基础之函数进阶

    假如有一个函数,实现返回两个数中的较大值: def my_max(x,y): m = x if x>y else y return mbigger = my_max(10,20)print(bi ...

  5. js创建jsonArray传输至后台及后台解析

    //产品清单 //产品数量长度 var cnbvLength = FieldCount9 + 1; var arrayList=[]; for(var i = 0; i < cnbvLength ...

  6. 链式栈的C++实现

    这是去年的内容,之前放在github的一个被遗忘的reporsity里面,今天看到了就拿出来 #include<iostream> #include<string> using ...

  7. CF1151F Sonya and Informatics

    cf luogu 我们最终要的序列一定是前面全是0,后面全是1,假设总共\(m\)个0,那么这等价于前\(m\)位0的个数为\(m\).当然一开始可能数量没有\(m\) 那就把前\(m\)位0的数量作 ...

  8. js之运算符(算术运算符)

    Javascript中的运算符大多是由标点符号少数由关键字表示.可以根据其操作数的个数进行分类.大多数运算符是一个二元运算符,将两个表达式合成一个比较复杂的表达式.还有需要注意的一点是运算符的优先级, ...

  9. leetcode297. 二叉树的序列化与反序列化

    代码 /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * ...

  10. 内存不足导致mysql关闭,CentOS6.5增加swap分区

    某日发现mysql自动关闭了,查找错误日志发现以下错误 2017-07-14 13:07:30 5494 [Note] InnoDB: Initializing buffer pool, size = ...