BZOJ 1930 吃豆豆(费用流)
首先这题的两条线不相交的限制可以去掉,因为如果相交的话把点换一换是不影响最终结果的。
剩下的费用流建图是显然的,把点拆为两个,建立超级源点s和源点ss汇点t,连边(s,ss,2,0). 对于每个点,连边(ss,i,1,0), (i,i',1,1),(i',t,1,0).
这样跑一遍费用流就行了,然而此题的边数可以达到n^2.无疑是OLE的。需要优化。
容易发现,对于点(i,j),(j,k),(i,k).如果这些点都可以互相到达的话,那么(i,k)这条边是不必要的。因为通过j到达k是不会比结果劣的。
所以启发我们将点按x坐标以第一关键字排序,y第二关键字排序。对于相同的列,选择大于前一列的y坐标且最小的点连边。
这样建边之后还存在一个问题,可能有个点两个吃豆人都需要经过,于是再建边(i,i',1,0),(i',j,2,0).
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi 3.1415926535
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
int res=, flag=;
char ch;
if((ch=getchar())=='-') flag=;
else if(ch>=''&&ch<='') res=ch-'';
while((ch=getchar())>=''&&ch<='') res=res*+(ch-'');
return flag?-res:res;
}
void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
}
const int N=;
//Code begin... struct Node{int x, y;}node[];
struct Edge{int to, next, cap, flow, cost;}edge[];
int head[N], tol, pre[N], dis[N], nn;
bool vis[N];
queue<int>q; void init(int n){nn=n; tol=; mem(head,-);}
void addedge(int u, int v, int cap, int cost){
edge[tol].to=v; edge[tol].cap=cap; edge[tol].cost=cost; edge[tol].flow=; edge[tol].next=head[u]; head[u]=tol++;
edge[tol].to=u; edge[tol].cap=; edge[tol].cost=-cost; edge[tol].flow=; edge[tol].next=head[v]; head[v]=tol++;
}
bool spfa(int s, int t){
FO(i,,nn) dis[i]=INF, vis[i]=false, pre[i]=-;
dis[s]=; vis[s]=true; q.push(s);
while (!q.empty()) {
int u=q.front(); q.pop(); vis[u]=false;
for (int i=head[u]; i!=-; i=edge[i].next) {
int v=edge[i].to;
if (edge[i].cap>edge[i].flow&&dis[v]>dis[u]+edge[i].cost) {
dis[v]=dis[u]+edge[i].cost; pre[v]=i;
if (!vis[v]) vis[v]=true, q.push(v);
}
}
}
if (pre[t]==-) return false;
else return true;
}
int minCostMaxflow(int s, int t, int &cost){
int flow=; cost=;
while (spfa(s,t)) {
int Min=INF;
for (int i=pre[t]; i!=-; i=pre[edge[i^].to]) {
if (Min>edge[i].cap-edge[i].flow) Min=edge[i].cap-edge[i].flow;
}
for (int i=pre[t]; i!=-; i=pre[edge[i^].to]) {
edge[i].flow+=Min; edge[i^].flow-=Min; cost+=edge[i].cost*Min;
}
flow+=Min;
}
return flow;
}
bool comp(Node a, Node b){
if (a.x==b.x) return a.y<b.y;
else return a.x<b.x;
}
int main ()
{
int n, s, ss, t;
scanf("%d",&n);
s=; ss=*n+; t=*n+;
init(t+);
addedge(s,ss,,);
FOR(i,,n) {
scanf("%d%d",&node[i].x,&node[i].y);
addedge(ss,i,,); addedge(i,n+i,,-); addedge(i,n+i,,); addedge(n+i,t,,);
}
sort(node+,node+n+,comp);
FOR(i,,n) {
int mi=INF, now=;
FOR(j,i+,n) {
if (now==node[j].x||node[j].y<node[i].y) continue;
if (node[j].y<mi) mi=node[j].y, now=node[j].x, addedge(n+i,j,,);
}
}
int ans;
minCostMaxflow(s,t,ans);
printf("%d\n",-ans);
return ;
}
BZOJ 1930 吃豆豆(费用流)的更多相关文章
- bzoj 1930: [Shoi2003]pacman 吃豆豆 [费用流]
1930: [Shoi2003]pacman 吃豆豆 题意:两个PACMAN吃豆豆.一开始的时候,PACMAN都在坐标原点的左下方,豆豆都在右上方.PACMAN走到豆豆处就会吃掉它.PACMAN行走的 ...
- [bzoj 1449] 球队收益(费用流)
[bzoj 1449] 球队收益(费用流) Description Input Output 一个整数表示联盟里所有球队收益之和的最小值. Sample Input 3 3 1 0 2 1 1 1 1 ...
- BZOJ.2597.[WC2007]剪刀石头布(费用流zkw)
BZOJ 洛谷 \(Description\) 给定一张部分边方向已确定的竞赛图.你需要给剩下的边确定方向,使得图中的三元环数量最多. \(n\leq100\). \(Solution\) 这种选择之 ...
- bzoj 1070: [SCOI2007]修车 费用流
1070: [SCOI2007]修车 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2785 Solved: 1110[Submit][Status] ...
- BZOJ 3171 循环格(费用流)
题意 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位置(r,c),你可以沿着箭头防线在格子间行走.即如果(r ...
- BZOJ 1070 修车 【费用流】
Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同 的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序, ...
- BZOJ 1927 星际竞速(费用流)
考虑费用流,题目要求走n个点都走完且恰好一次,显然流量的限制为n. 建立源点s和汇点t,并把每个星球拆成两个点i和i',分别表示已到达该点和经过该点. 对于能力爆发,建边(s,i',1,w). 对应高 ...
- BZOJ 1221 软件开发(费用流)
容易看出这是显然的费用流模型. 把每天需要的餐巾数作为限制.需要将天数拆点,x’表示每天需要的餐巾,x’’表示每天用完的餐巾.所以加边 (s,x',INF,0),(x'',t,INF,0). 餐巾可以 ...
- bzoj 1520 [POI2006]Szk-Schools 费用流
[POI2006]Szk-Schools Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 743 Solved: 381[Submit][Status][ ...
随机推荐
- 20145234黄斐《信息安全系统设计基础》第七周(Linux命令复习)
已经到了11月,学期过半,而<信息安全系统设计基础>这门课也要到了期中考试了.所以,我在这里,对前半个学期的最基础的知识,做一个复习 复习计划分为两步,本次为Linux命令,下次计划复习g ...
- 北京Uber优步司机奖励政策(3月31日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- 北京Uber优步司机奖励政策(2月2日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- 06003_redis在Linux上的安装
1.redis-3.0.0.tar.gz下载链接:redis-3.0.0.tar.gz下载 密码:wpbu 2.安装redis编译的c环境,yum install gcc-c++ : 3.将redis ...
- java nio之Buffer
一.JAVA NIO 是在和channel交互的时候使用的.Channel将数据读入缓冲区,然后我们又从缓冲区访问数据.写数据时,首先将要发送的数据按顺序填入缓冲区.基本上,缓冲区只是一个列表,它的所 ...
- oracle 建立一个视图,然后授权其他用户访问
grant select on V_LIC_ENTRY_HZ_STATUS to ielicr2013; create or replace view dept_sum_vw (name,minsal ...
- solr 学习
点击dataimport 没有handler数据 重启下 tomcat 如果没有权限 Cannot find ./catalina.shThe file is absent or does not ...
- “腾讯WeTest助力《龙珠直播》盘点APP质量问题”
WeTest 导读 据调查数据表明,移动端用户在使用APP时如果遇到了闪退等兼容性问题,20%的用户会选择直接卸载. 2016年,被称为中国直播元年.随着各类直播平台的疯狂生长与扩散,直播产品在内容, ...
- Qt-网络与通信-TCP版本聊天程序
代码在公司,考不出来,智能用书里自带的例子来写了. 不过这个TCP版本的程序并没有出来书上的效果,具体问题出在哪里还没有找到,运行书里自带的代码也是这样. 另外发现一个问题 Qt5.8.0VS版本对中 ...
- 怎样通过Qt编写C/C++代码查询当前Linux的版本号?
遇到一个问题:如题. 我的开发环境是:嵌入式ARM + Linux系统 + Qt 4.5 + C/C++ 现在需要查询 当前Linux系统的版本号. 问题: 1)Qt 4.5 提供怎样的API来获取? ...