CF704D Captain America

CF704D Captain America 

想到了上下界网络流,但是建图一时智障不会了。。

都选择花费较大的。

合法情况下,尽量多地变成小的。

为了使得选择一个点,可以使行、列限制都流过恰好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*
*/
原文地址:https://www.cnblogs.com/Miracevin/p/10945452.html