【CF704D】Captain America
跟着长郡军团做的一道题。
题面
https://www.luogu.org/problem/CF704D
题解
上下界网络流傻逼题。
注意判无解的第二种姿势:$l[i]>r[i]$
#include<cstdio> #include<cstring> #include<iostream> #include<queue> #include<vector> #include<algorithm> #include<map> #define LL long long #define ri register int #define N 250000 #define INF 1000000007 using namespace std; int n,m,ccx=0,ccy=0,x[N],y[N]; int p[N],le[N],re[N]; int numx[N],numy[N]; map<int,int> otx,oty; int idx(int x) { if (!otx.count(x)) otx[x]=++ccx; return otx[x]; } int idy(int y) { if (!oty.count(y)) oty[y]=++ccy; return oty[y]; } struct graph { vector<int> ed[N],w,to; int d[N],cur[N]; int S,T; void add_edge(int u,int v,int tw) { to.push_back(v); w.push_back(tw); ed[u].push_back(to.size()-1); to.push_back(u); w.push_back(0); ed[v].push_back(to.size()-1); } bool bfs() { queue<int> q; memset(d,0x3f,sizeof(d)); d[S]=0; q.push(S); while (!q.empty()) { int x=q.front(); q.pop(); for (ri i=0;i<ed[x].size();i++) { int e=ed[x][i]; if (d[x]+1<d[to[e]] && w[e]) { d[to[e]]=d[x]+1; q.push(to[e]); } } } return d[T]<INF; } int dfs(int x,int limit) { if (x==T || limit==0) return limit; int sum=0; for (ri &i=cur[x];i<ed[x].size();i++) { int e=ed[x][i]; if (w[e] && d[x]+1==d[to[e]]) { int f=dfs(to[e],min(limit,w[e])); if (!f) continue; sum+=f; limit-=f; w[e]-=f; w[1^e]+=f; if (!limit) return sum; } } return sum; } int dinic() { int ret=0; while (bfs()) { memset(cur,0,sizeof(cur)); ret+=dfs(S,INF); } return ret; } } G; int main() { int t,l,d; LL r,b; scanf("%d %d",&n,&m); scanf("%lld %lld",&r,&b); for (ri i=1;i<=n;i++) { scanf("%d %d",&x[i],&y[i]); x[i]=idx(x[i]);y[i]=idy(y[i]); numx[x[i]]++; numy[y[i]]++; } for (ri i=1;i<=ccx;i++) le[i]=0,re[i]=numx[i]; for (ri i=1;i<=ccy;i++) le[ccx+i]=0,re[ccx+i]=numy[i]; for (ri i=1;i<=m;i++) { scanf("%d %d %d",&t,&l,&d); if (t==1) { if (!otx.count(l)) continue; int nx=otx[l]; l=otx[l]; if ((numx[l]+d)%2==0) { le[nx]=max(le[nx],(numx[l]-d)/2); re[nx]=min(re[nx],(numx[l]+d)/2); } else { le[nx]=max(le[nx],(numx[l]-d+1)/2); re[nx]=min(re[nx],(numx[l]+d-1)/2); } } else { if (!oty.count(l)) continue; int ny=oty[l]+ccx; l=oty[l]; if ((numy[l]+d)%2==0) { le[ny]=max(le[ny],(numy[l]-d)/2); re[ny]=min(re[ny],(numy[l]+d)/2); } else { le[ny]=max(le[ny],(numy[l]-d+1)/2); re[ny]=min(re[ny],(numy[l]+d-1)/2); } } } int S=0,T=ccx+ccy+1; int SS=ccx+ccy+2,TT=ccx+ccy+3; for (ri i=1;i<=ccx;i++) { if (re[i]<le[i]) { printf("-1"); return 0; } p[S]-=le[i],p[i]+=le[i]; G.add_edge(S,i,re[i]-le[i]); } for (ri i=ccx+1;i<=ccx+ccy;i++) { if (re[i]<le[i]) { printf("-1"); return 0; } p[T]+=le[i],p[i]-=le[i]; G.add_edge(i,T,re[i]-le[i]); } for (ri i=1;i<=n;i++) G.add_edge(x[i],ccx+y[i],1); int ds=0; for (ri i=S;i<=T;i++) { if (p[i]>0) G.add_edge(SS,i,p[i]),ds+=p[i]; else if (p[i]<0) G.add_edge(i,TT,-p[i]); } G.add_edge(T,S,INF); G.S=SS; G.T=TT; int tm=G.dinic(); if (tm!=ds) { printf("-1"); return 0;} int flow1=G.w[G.w.size()-1]; G.w[G.w.size()-2]=G.w[G.w.size()-1]=0; for (ri i=0,l=G.w.size();i<l;i++) { if (G.to[i]==SS || G.to[i]==TT || G.to[i^1]==SS || G.to[i^1]==TT) G.w[i]=0; } G.S=S; G.T=T; int flow=flow1+G.dinic(); if (r<b) { LL ans=r*1LL*flow+(n-flow)*1LL*b; printf("%lld\n",ans); for (ri i=0,l=G.to.size();i<l;++i) { if (G.to[i]>ccx && G.to[i]<=ccx+ccy && G.to[i^1]>=1 && G.to[i^1]<=ccx) putchar(G.w[i]?'b':'r'); } } else { LL ans=r*1LL*(n-flow)+b*1LL*flow; printf("%lld\n",ans); for (ri i=0,l=G.to.size();i<l;++i) { if (G.to[i]>ccx && G.to[i]<=ccx+ccy && G.to[i^1]>=1 && G.to[i^1]<=ccx) putchar(G.w[i]?'r':'b'); } } return 0; }