题意:给你一个棋盘,棋盘上有一些棋子,有一些规定,规定超过多少行或者多少列后只能取不超过k的棋子。
题解:棋盘问题是一个很经典的网络流问题。
建图还是比较好想的,但是不会跑最大费用流,赛后补了一下。
但是好像这道题有问题,最大费用最大流也能过。
但是明显不符合费用最大时流最大。
所以想一下最小费用最大流的做法,首先费用取反,这样就变成了最小费用,
每次跑一条s到t的最短路,然后减去这条路的流量。这样保证每次跑出来的最短路是越来越大的。
所以当最短路第一次大于0时,接下来所有的流量的费用都大于0,会使费用变大,所以直接跳出。
建图的话,感觉类似并查集的思路,我想了一种很low的建法,题解的建法就很优美了,所以又照着题解建了一波。
#include <bits/stdc++.h>
using namespace std;
#define N 4010
#define inf 0x3f3f3f3f
#define go(i,a,b) for(int i=(a);i<=(b);i++)
#define dep(i,a,b) for(int i=(a);i>=(b);i--)
struct no{
int to,n,cap,flow,cost;
};no d[N*10];
queue<int>q;
int h[N],dp[N],p[N],f[N],in[N], tot,need;
void add(int u,int to,int w,int v){
//cout<<u<<' '<<to<<' '<<w<<' '<<v<<'+'<<endl;
d[tot]={to,h[u],w,0,v };h[u]=tot++;
d[tot]={u,h[to],0,0,-v};h[to]=tot++;
}
bool spfa(int s,int e){
memset(dp,inf,sizeof(dp));
memset(p,-1,sizeof(p));
memset(f,0,sizeof(f));
q.push(s);dp[s]=0;
while(!q.empty()){
int x=q.front();q.pop();
f[x]=0;
for(int i=h[x];i!=-1;i=d[i].n){
int to=d[i].to,cost=d[i].cost;
if(dp[x]+cost<dp[to]&&d[i].cap>d[i].flow){
p[to]=i;
dp[to]=dp[x]+cost;
if(f[to])continue;
f[to]=1;
q.push(to);
}
}
}
return p[e]!=-1&&dp[e]<0;
}
int Cost = 0, Flow = 0;
int dini(int s,int e){
while(spfa(s,e)){
int Min=inf;
for(int i=p[e];i!=-1;i=p[d[i^1].to])
Min=min(Min,d[i].cap-d[i].flow);
for(int i=p[e];i!=-1;i=p[d[i^1].to]){
d[i].flow+=Min;
d[i^1].flow-=Min;
Cost+=d[i].cost*Min;
}
Flow+=Min;
}
}
int discre(int a[],int n){
sort(a+1,a+n+1);
//go(i,1,n)cout<<a[i]<<' ';cout<<endl;
return unique(a+1,a+n+1)-a-1;
}
inline int getdiscre(int a[],int n,int w){
return lower_bound(a+1,a+n+1,w)-a;
}
int n,m,c_siz,r_siz;
inline int cid(int x){return x; }
inline int rid(int x){return x+c_siz+1; }
char op[10];
int c1[N],c2[N],r1[N],r2[N],id,k,x[N],y[N];
int main()
{
cin>>n;
memset(c2,inf,sizeof(c2));
memset(r2,inf,sizeof(r2));
memset(h,-1,sizeof(h));
go(i,1,n)
scanf("%d%d",&x[i],&y[i]),
c1[i]=x[i],r1[i]=y[i];
c_siz=discre(c1,n),r_siz=discre(r1,n);
go(i,1,n)add(cid(getdiscre(c1,c_siz,x[i])),rid(getdiscre(r1,r_siz,y[i])),1,-i);
cin>>m;
go(i,1,m){
scanf("%s%d%d",op,&id,&k);
if(op[0]=='C'){
id=getdiscre(r1,r_siz,id);
if(id<=r_siz)r2[id]=min(r2[id],k);
}
else {
id=getdiscre(c1,c_siz,id);
if(id<=c_siz)c2[id]=min(c2[id],k);
}
}
dep(i,c_siz,1)
add(cid(i-1),cid(i),c2[i],0);
dep(i,r_siz,1)
add(rid(i),rid(i-1),r2[i],0);
dini(0,c_siz+1);
printf("%d\n",-Cost);
}