CF704D Captain America

Link
不失一般性,不妨认为\(r\le b\)
假如我们先全部选\(b\),那么我们需要做的就是最大化将\(b\)变为\(r\)的个数。
离散化,并对每一行和每一列新建一个点。
对于第\(i\)行,假如原本这一行有\(c_i\)\(b\),最紧的限制为\(d_i\),那么我们需要将\([\lceil\frac{c_i-d_i}2\rceil,\lfloor\frac{c_i+d_i}2\rfloor]\)\(r\)变成\(b\)
对于第\(i\)列同理,记这一列原本的\(b\)的个数和最紧的限制为\(C_i,D_i\)
那么我们可以将其转化为有源汇上下界最大流模型:
\(s\rightarrow u_i:[\lceil\frac{c_i-d_i}2\rceil,\lfloor\frac{c_i+d_i}2\rfloor]\)(每一行的限制)
\(v_i\rightarrow t:[\lceil\frac{C_i-D_i}2\rceil,\lfloor\frac{C_i+D_i}2\rfloor]\)(每一列的限制)
\(\forall(x,y),u_x\rightarrow v_y:[0,1]\)(将一个\(b\)变成一个\(r\)

#include<queue>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#include<unordered_map>
const int N=200007,M=N*5,inf=1e9;
char ibuf[(1<<23)+1],*iS=ibuf;
int x[N],y[N],tx[N],ty[N],cx[N],cy[N],lx[N],ly[N],id[N],d[N];
int s,t,S,T,tot=1,head[N],ver[M],edge[M],next[M],cur[N],dep[N];std::queue<int>q;
std::unordered_map<int,int>hx,hy;
int read(){int x=0;while(isspace(*iS))++iS;while(isdigit(*iS))(x*=10)+=*iS++&15;return x;}
void add(int u,int v,int w){ver[++tot]=v,next[tot]=head[u],edge[tot]=w,head[u]=tot,ver[++tot]=u,next[tot]=head[v],edge[tot]=0,head[v]=tot;}
void Add(int u,int v,int l,int r){add(u,v,r-l),d[u]-=l,d[v]+=l;}
int bfs(int s,int t)
{
    memset(dep+1,-1,T<<2),memcpy(cur+1,head+1,T<<2),dep[s]=0,q.push(s);
    for(int i,u,v;!q.empty();) for(u=q.front(),q.pop(),i=head[u];i;i=next[i]) if(!~dep[v=ver[i]]&&edge[i]) dep[v]=dep[u]+1,q.push(v);
    return ~dep[t];
}
int dfs(int u,int t,int lim)
{
    if(!lim||u==t) return lim;
    int v,flow=0;
    for(int&i=cur[u],f;i;i=next[i])
	if(edge[i]&&dep[v=ver[i]]==dep[u]+1)
	{
	    flow+=(f=dfs(v,t,std::min(lim,edge[i]))),lim-=f,edge[i]-=f,edge[i^1]+=f;
	    if(!lim) break;
	}
    return flow;
}
int dinic(int s,int t){int r=0;while(bfs(s,t))r+=dfs(s,t,inf);return r;}
int main()
{
    fread(ibuf,1,1<<23,stdin);
    int n=read(),m=read(),r=read(),b=read(),mx,my,f=0,sum=0,ans=0;
    if(r>b) std::swap(r,b),f=1;
    for(int i=1;i<=n;++i) x[i]=read(),y[i]=read();
    memcpy(tx+1,x+1,n<<2),memcpy(ty+1,y+1,n<<2);
    std::sort(tx+1,tx+n+1),std::sort(ty+1,ty+n+1);
    mx=std::unique(tx+1,tx+n+1)-tx-1,my=std::unique(ty+1,ty+n+1)-ty-1;
    s=mx+my+1,t=s+1,S=t+1,T=S+1,add(t,s,inf);
    for(int i=1;i<=mx;++i) hx[tx[i]]=i;
    for(int i=1;i<=my;++i) hy[ty[i]]=i;
    for(int i=1;i<=n;++i) ++cx[x[i]=hx[x[i]]],++cy[y[i]=hy[y[i]]];
    for(int i=1;i<=n;++i) add(x[i],y[i]+mx,1),id[i]=tot^1;
    memcpy(lx+1,cx+1,mx<<2),memcpy(ly+1,cy+1,my<<2);
    for(int i=1,o,l,d;i<=m;++i)
    {
	o=read(),l=read(),d=read();
	if(o&1) {if(hx.count(l)) l=hx[l],lx[l]=std::min(lx[l],d);}
	else {if(hy.count(l)) l=hy[l],ly[l]=std::min(ly[l],d);}
    }
    for(int i=1;i<=mx;++i) if(cx[i]&1&&!lx[i]) return puts("-1"),0; else Add(s,i,(cx[i]-lx[i]+1)/2,(cx[i]+lx[i])/2);
    for(int i=1;i<=my;++i) if(cy[i]&1&&!ly[i]) return puts("-1"),0; else Add(i+mx,t,(cy[i]-ly[i]+1)/2,(cy[i]+ly[i])/2);
    for(int i=1;i<=t;++i) if(d[i]>0) add(S,i,d[i]),sum+=d[i]; else if(d[i]<0) add(i,T,-d[i]);
    if((ans=dinic(S,T))^sum) return puts("-1"),0;
    ans=dinic(s,t),printf("%lld\n",1ll*ans*r+1ll*(n-ans)*b);
    for(int i=1;i<=n;++i) putchar(edge[id[i]]^f? 'b':'r');
}
posted @ 2020-02-26 20:35  Shiina_Mashiro  阅读(153)  评论(0编辑  收藏  举报