HDU-6532 Chessboard 2019广东省省赛B题(费用流)
比赛场上很容易想到是费用流,但是没有想到建图方法qwq,太弱了。
这里直接贴官方题解:
费用流。离散化坐标,每行用一个点表示,每列也用一个点表示。表示第i-1行的点向表示第i行的点连边,容量为第i行及以后能拿的棋子数的上限,费用为0,同理表示相邻列的点两两连边。若第i行第j列上有棋子,则表示第i行的点向表示第j列的点连边,容量为1,费用为该棋子的价值。可以定义源点表示第0行,汇点表示第0列,源点到汇点的最大费用流即为答案。
就是按照题解的建图方法,还有一些小细节:先要排序排除无用限制来减少限制边数,不然会超时。我用的办法是,按限制从小到大排序,大限制当且仅当它的行数小于小限制行数时才有用。列同理。这里想不明白的建议画图细细想。然后就是连边来表示限制条件:行的话就是(i-1)->i行连边,列的话就是i->(i-1)列连边,这是因为0行是源点0列是汇点所致的,行点要靠它的入边来限制流量,列点要靠出边来限制流量。
细节详见代码及注释:
#include<bits/stdc++.h>
using namespace std;
const int N=+;
const int M=+;
const int INF=0x3f3f3f3f;
int n,m,r,c,s,t,maxflow,mincost;
int nx,ny,x[N],y[N],xx[N],yy[N],bx[N],by[N];
struct edge{
int nxt,to,cap,cost;
}edges[M<<];
int cnt=,head[N],pre[N]; struct dat{ int t,l; } R[M],C[M];
bool cmp(dat a,dat b) { return a.l<b.l || a.l==b.l && a.t<b.t; } void add_edge(int x,int y,int z,int c) {
edges[++cnt].nxt=head[x]; edges[cnt].to=y; edges[cnt].cap=z; edges[cnt].cost=c; head[x]=cnt;
} queue<int> q;
int dis[N],lim[N];
bool inq[N];
bool spfa(int s,int t) {
while (!q.empty()) q.pop();
memset(dis,0x3f,sizeof(dis));
memset(inq,,sizeof(inq));
dis[s]=; inq[s]=; lim[s]=INF; q.push(s);
while (!q.empty()) {
int x=q.front(); q.pop();
for (int i=head[x];i;i=edges[i].nxt) {
edge e=edges[i];
if (e.cap && dis[x]+e.cost<dis[e.to]) {
dis[e.to]=dis[x]+e.cost;
pre[e.to]=i; //即e.to这个点是从i这条边来的
lim[e.to]=min(lim[x],e.cap);
if (!inq[e.to]) { q.push(e.to); inq[e.to]=; }
}
}
inq[x]=;
}
return !(dis[t]==INF);
} void MCMF() {
maxflow=; mincost=;
while (spfa(s,t)) {
int now=t;
maxflow+=lim[t];
mincost+=lim[t]*dis[t];
while (now!=s) {
edges[pre[now]].cap-=lim[t];
edges[pre[now]^].cap+=lim[t];
now=edges[pre[now]^].to;
}
}
} int main()
{
scanf("%d",&n);
for (int i=;i<=n;i++) scanf("%d%d",&x[i],&y[i]),bx[i]=x[i],by[i]=y[i];
nx=ny=n;
scanf("%d",&m);
char opt[];
for (int i=;i<=m;i++) {
int tx,ty; scanf("%s%d%d",opt,&tx,&ty);
if (opt[]=='R') R[++r]=(dat){tx,ty};
if (opt[]=='C') C[++c]=(dat){tx,ty};
}
int tmp=;
sort(R+,R+r+,cmp);
for (int i=;i<=r;i++) //排除行无用限制
if (tmp== || R[i].t<R[tmp].t) R[++tmp]=R[i],bx[++nx]=R[i].t;
r=tmp; tmp=;
sort(C+,C+c+,cmp);
for (int i=;i<=c;i++) //排除列无用限制
if (tmp== || C[i].t<C[tmp].t) C[++tmp]=C[i],by[++ny]=C[i].t;
c=tmp; sort(bx+,bx+nx+); nx=unique(bx+,bx+nx+)-(bx+); //离散化
sort(by+,by+ny+); ny=unique(by+,by+ny+)-(by+); //离散化 for (int i=;i<=n;i++) {
int tx=lower_bound(bx+,bx+nx+,x[i])-bx;
int ty=lower_bound(by+,by+ny+,y[i])-by;
add_edge(tx,nx++ty,,-i); add_edge(nx++ty,tx,,i); //棋子连边
}
memset(xx,0x3f,sizeof(xx));
memset(yy,0x3f,sizeof(yy));
for (int i=;i<=r;i++) {
int tx=lower_bound(bx+,bx+nx+,R[i].t)-bx;
xx[tx]=min(xx[tx],R[i].l); //先求好限制条件,xx[i]代表i行及以后的最小限制
}
for (int i=;i<=c;i++) {
int ty=lower_bound(by+,by+ny+,C[i].t)-by;
yy[ty]=min(yy[ty],C[i].l); //列同行同理
}
//这里是关键:行i-1->i为了限制i的出流,列i->i-1为了限制i的出流
for (int i=;i<=nx;i++) add_edge(i-,i,xx[i],),add_edge(i,i-,,);
for (int i=;i<=ny;i++) add_edge(nx++i,nx++i-,yy[i],),add_edge(nx++i-,nx++i,,); s=; t=nx+;
MCMF();
cout<<-mincost<<endl;
return ;
}
HDU-6532 Chessboard 2019广东省省赛B题(费用流)的更多相关文章
- ACM-ICPC 2019南昌网络赛I题 Yukino With Subinterval
ACM-ICPC 2019南昌网络赛I题 Yukino With Subinterval 题目大意:给一个长度为n,值域为[1, n]的序列{a},要求支持m次操作: 单点修改 1 pos val 询 ...
- TI MSP430工程配置及2019年电赛A题编程示例(使用430 F5529)
配置 第一步:右击工程,选择Options 第二步:在General Options的Target选项卡里选择对应的器件Device,这里是MSP430G2231 第三步:在Debugger里选择FE ...
- ACM-ICPC 2019南昌网络赛F题 Megumi With String
ACM-ICPC 南昌网络赛F题 Megumi With String 题目描述 给一个长度为\(l\)的字符串\(S\),和关于\(x\)的\(k\)次多项式\(G[x]\).当一个字符串\(str ...
- 2016青岛区域赛.Coding Contest(费用流 + 概率计算转换为加法计算)
Coding Contest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)To ...
- Tour HDU - 3488 有向环最小权值覆盖 费用流
http://acm.hdu.edu.cn/showproblem.php?pid=3488 给一个无源汇的,带有边权的有向图 让你找出一个最小的哈密顿回路 可以用KM算法写,但是费用流也行 思路 1 ...
- 2019建模美赛B题(派送无人机)M奖论文
昨天上午出了建模美赛的结果,我们小组获得的是M奖,感觉挺开心的.我一直觉得拿O奖那种是个概率事件,需要天时地利人和的各种因素都合适才行,所以看到自己是M奖,感觉自己的能力已经得到了认可就很满意了.今天 ...
- [2019南京网络赛D题]Robots
题目链接 2019.9.2更新 第二天睡醒想了想发现好像搜一遍就可以过,赛时写的花里胡哨的还错了,太菜了QAQ #include<bits/stdc++.h> using namespac ...
- hdu 4031 2011成都赛区网络赛A题 线段树 ***
就是不知道时间该怎么处理,想了好久,看了别人的题解发现原来是暴力,暴力也很巧妙啊,想不出来的那种 -_-! #include<cstdio> #include<iostream&g ...
- HDU 4119Isabella's Message2011成都现场赛I题(字符串模拟)
Isabella's Message Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
随机推荐
- new做了些什么?
new做了些什么? function People(name, age){ this.name = name; this.age = age; }; var xiaoming = new People ...
- html中代替空格、大于号、小于号等字符编码
数字表示法的不方便之处,在于必须知道每个字符的码点,很难记忆.为了能够快速输入,HTML 为一些特殊字符,规定了容易记忆的名字,允许通过名字来表示它们,这称为实体表示法(entity). 实体的写法是 ...
- 利用Swiperefreshlayout实现下拉刷新功能的技术探讨
在常见的APP中通常有着下拉页面从而达到刷新页面的功能,这种看似简单的功能有着花样繁多的实现方式.而利用Swiperefreshlayout实现下拉刷新功能则是其中比较简明扼要的一种. 一般来说,在竖 ...
- MD相关语法
原文链接:https://www.jianshu.com/p/96ecaa2cc989 标题 一个#表示一级标题,最多6个表示6级标题 h1 h2 h3 h4 h5 h6 列表 无序列表,用 * + ...
- 绘图matplotlib
前言 matplotlib是python的一个绘图库,如果你没有绘制过图,可以先试试js的绘图库http://www.runoob.com/highcharts/highcharts-line-lab ...
- 第8篇NFS PersistentVolume
一.部署nfs服务端: k8s-master 节点上搭建了 NFS 服务器,也可以在部署节点搭建,原理一样 (1)安装nfs服务: yum install -y nfs-utils rpcbind v ...
- java 方法的定义与调用
/* 定义一个方法的格式: public static void 方法名称(){ 方法体 } 方法名称的命名规则和变量一样,使用小驼峰 方法体:也就是大括号里面的可以包含任何语句 注意事项: 1.方法 ...
- 带你逐行阅读redux源码
带你逐行阅读redux源码 redux版本:2019-7-17最新版:v4.0.4 git 地址:https://github.com/reduxjs/redux/tree/v4.0.4 redux目 ...
- 在Anaconda环境下使用Jupyter Notebook
!!!Anaconda 和 Jupyter Notebook 在 zsh 环境下不能正常使用! 启动建立的 Anaconda 环境 安装 nb_conda:conda install nb_conda ...
- pywin3的简介
微软Windows的Python扩展提供了对Win32 API的访问.创建和使用COM对象的能力以及PythOnWin环境.Pywin32是一个Python库,为python提供访问Wind ...