比赛场上很容易想到是费用流,但是没有想到建图方法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题(费用流)的更多相关文章

  1. ACM-ICPC 2019南昌网络赛I题 Yukino With Subinterval

    ACM-ICPC 2019南昌网络赛I题 Yukino With Subinterval 题目大意:给一个长度为n,值域为[1, n]的序列{a},要求支持m次操作: 单点修改 1 pos val 询 ...

  2. TI MSP430工程配置及2019年电赛A题编程示例(使用430 F5529)

    配置 第一步:右击工程,选择Options 第二步:在General Options的Target选项卡里选择对应的器件Device,这里是MSP430G2231 第三步:在Debugger里选择FE ...

  3. ACM-ICPC 2019南昌网络赛F题 Megumi With String

    ACM-ICPC 南昌网络赛F题 Megumi With String 题目描述 给一个长度为\(l\)的字符串\(S\),和关于\(x\)的\(k\)次多项式\(G[x]\).当一个字符串\(str ...

  4. 2016青岛区域赛.Coding Contest(费用流 + 概率计算转换为加法计算)

    Coding Contest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  5. Tour HDU - 3488 有向环最小权值覆盖 费用流

    http://acm.hdu.edu.cn/showproblem.php?pid=3488 给一个无源汇的,带有边权的有向图 让你找出一个最小的哈密顿回路 可以用KM算法写,但是费用流也行 思路 1 ...

  6. 2019建模美赛B题(派送无人机)M奖论文

    昨天上午出了建模美赛的结果,我们小组获得的是M奖,感觉挺开心的.我一直觉得拿O奖那种是个概率事件,需要天时地利人和的各种因素都合适才行,所以看到自己是M奖,感觉自己的能力已经得到了认可就很满意了.今天 ...

  7. [2019南京网络赛D题]Robots

    题目链接 2019.9.2更新 第二天睡醒想了想发现好像搜一遍就可以过,赛时写的花里胡哨的还错了,太菜了QAQ #include<bits/stdc++.h> using namespac ...

  8. hdu 4031 2011成都赛区网络赛A题 线段树 ***

    就是不知道时间该怎么处理,想了好久,看了别人的题解发现原来是暴力,暴力也很巧妙啊,想不出来的那种  -_-! #include<cstdio> #include<iostream&g ...

  9. HDU 4119Isabella's Message2011成都现场赛I题(字符串模拟)

    Isabella's Message Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

随机推荐

  1. go语言从例子开始之Example8.数组

    在 Go 中,数组 是一个固定长度的数列. package main import "fmt" func main() { 这里我们创建了一个数组 a 来存放刚好 5 个 int. ...

  2. js实现的简单遮罩层

    超级简单的一个实现,可能会有局限性,贵在简单易懂,使用的时候执行前loading,执行成功后loaded /* * 显示loading遮罩层 */ function loading() { var m ...

  3. JAVA读取Excel2003、2007、2010教程

    import java.io.File;import java.io.FileInputStream;import org.apache.poi.ss.usermodel.Row;import org ...

  4. Future模式的简单实现

    /** * 数据接口 */ public interface Data { public String getResult(); } /** * 最终需要使用的数据模型 */ public class ...

  5. boost smart pointer

    1. boost::scoped_ptr is a smart pointer that is the sole owner of a dynamically allocated object and ...

  6. 后端优化(2)—— BA与图优化

  7. 未来-YLB-二手市场:二手市场

    ylbtech-未来-YLB-二手市场:二手市场 1.返回顶部 1. 二手市场是人们将闲置不用的物品集中起来进行交换.交易的场所.在二手市场中买卖二手物品,价格低廉.二手交易市场又称跳蚤市场.   中 ...

  8. python3迷宫,多线程版

    上图: 直接上代码 #!/usr/bin/python3 #coding=GB2312 import tkinter as tk import threading import time import ...

  9. 关于sql中日期操作

    select * from account where  DAYOFWEEK('2019-11-30') =7 limit 10 DAYOFWEEK对应结果: 周日:1 周一:2 周二:3 周三:4 ...

  10. JS检查断网

    window.addEventListener('load', function() { function updateOnlineStatus(event) { var condition = na ...