想到了上下界网络流,但是建图一时智障不会了。。
都选择花费较大的。
合法情况下,尽量多地变成小的。
为了使得选择一个点,可以使行、列限制都流过恰好1点,
二分图,把这个点当做边连接行、列代表点即可。
上下界随便计算即可。
这里跑有源汇上下界最大流!
(开始想的是,都选择小的,再变成花费大的,这样就是费用流。然鹅费用流会TLE,而这里一点流量和一点费用是等价的!)
先构造可行流,拆掉多于边再跑最大流。
然后输出方案。
代码丑极。
#include<bits/stdc++.h> #define reg register int #define il inline #define fi first #define se second #define mk(a,b) make_pair(a,b) #define numb (ch^'0') #define pb push_back #define solid const auto & #define enter cout<<endl #define pii pair<int,int> using namespace std; typedef long long ll; template<class T>il void rd(T &x){ char ch;x=0;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x);} template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');} template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');} template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar(' ');} namespace Miracle{ const int N=100000+8; const int inf=0x3f3f3f3f; int n,m; int X[N],Y[N]; int tmp[N]; struct node{ int nxt,to; int w; }e[2*(N+N+N+N)]; int R,B; int hd[N],cnt=1; ll ans; int be[N]; int s,t; void add(int x,int y,int w){ e[++cnt].nxt=hd[x]; e[cnt].to=y;e[cnt].w=w; hd[x]=cnt; e[++cnt].nxt=hd[y]; e[cnt].to=x;e[cnt].w=0; hd[y]=cnt; } unordered_map<int,int>hang,lie,ch,cl; int flow; int d[N]; int dfs(int x,int flow){ if(x==t) return flow; int res=flow; for(reg i=hd[x];i&&res;i=e[i].nxt){ int y=e[i].to; if(d[y]==d[x]+1&&e[i].w){ int k=dfs(y,min(res,e[i].w)); if(!k) d[y]=0; e[i].w-=k; e[i^1].w+=k; // return k; res-=k; } } return flow-res; } int q[N],l,r; bool bfs(){ memset(d,0,sizeof d); l=1,r=0; q[++r]=t; d[t]=t+1; while(l<=r){ int x=q[l++]; // cout<<" xx "<<x<<endl; for(reg i=hd[x];i;i=e[i].nxt){ int y=e[i].to; if(e[i^1].w&&!d[y]){ d[y]=d[x]-1; q[++r]=y; if(y==s) return true; } } } return false; } int pos[N]; int chu[N]; int tot; struct LIM{ int typ,p,d; bool friend operator<(LIM a,LIM b){ return a.d<b.d; } }qs[N]; void die(){ printf("-1");exit(0); } int main(){ rd(n);rd(m); rd(R);rd(B); for(reg i=1;i<=n;++i){ rd(X[i]);rd(Y[i]); ++ch[X[i]];++cl[Y[i]]; } for(reg i=1;i<=m;++i){ rd(qs[i].typ);rd(qs[i].p);rd(qs[i].d); } sort(qs+1,qs+m+1); s=0,t=m+1; for(reg i=1;i<=m;++i){ // cout<<" limlimlim------------- "<<i<<" : "<<qs[i].typ<<" "<<qs[i].p<<" "<<qs[i].d<<endl; if(qs[i].typ==1){ if(hang.count(qs[i].p)||qs[i].d>=ch[qs[i].p]) continue; hang[qs[i].p]=i; int r=ch[qs[i].p]; int d=qs[i].d; int lo=(r-d+1)/2,hi=(r+d)/2; // cout<<" lo "<<lo<<" hi "<<hi<<endl; chu[s]+=lo; chu[i]-=lo; if(hi-lo<0){ die(); } add(s,i,hi-lo); }else{ if(lie.count(qs[i].p)||qs[i].d>=cl[qs[i].p]) continue; lie[qs[i].p]=i; int r=cl[qs[i].p]; int d=qs[i].d; int lo=(r-d+1)/2,hi=(r+d)/2; // cout<<" lo "<<lo<<" hi "<<hi<<endl; chu[i]+=lo; chu[t]-=lo; if(hi-lo<0){ die(); } add(i,t,hi-lo); } } for(reg i=1;i<=n;++i){ int le=hang[X[i]],ri=lie[Y[i]]; if(ri==0) ri=t; if(le==0) le=s; // cout<<" ii "<<i<<" le "<<le<<" ri "<<ri<<endl; add(le,ri,1); pos[i]=cnt-1; } memcpy(tmp,hd,sizeof hd); s=m+2,t=m+3; for(reg i=0;i<=m+1;++i){ if(chu[i]<0){ add(s,i,-chu[i]); }else{ add(i,t,chu[i]); flow+=chu[i]; } } // cout<<"st "<<flow<<endl; add(m+1,0,inf); ans=(ll)n*max(R,B); int now; while(bfs()){ while(now=dfs(s,inf)) flow-=now; } // cout<<"nd "<<flow<<" ans "<<ans<<endl; if(flow!=0){ die(); } memcpy(hd,tmp,sizeof tmp); s=0;t=m+1; while(bfs()){ while(now=dfs(s,inf)) flow+=now;//this flow is useless } for(reg i=1;i<=n;++i){ if(e[pos[i]].w==0){ ans-=abs(R-B); be[i]=0; }else{ be[i]=1; } } printf("%lld ",ans); for(reg i=1;i<=n;++i){ if(be[i]==1){ if(R<=B){ putchar('b'); }else{ putchar('r'); } }else { if(R<=B){ putchar('r'); }else{ putchar('b'); } } } return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* */