Codeforces – 321B

MCMF必须是满足流量最大为前提下的最小费用流(这里是最大费用流)

因此还必须不断地枚举m的流量才行

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 1e5+11;
const int oo = 0x3f3f3f3f;
int to[maxn<<1],cost[maxn<<1],cap[maxn<<1],flow[maxn<<1],nxt[maxn<<1];
int head[maxn],tot;
void init(){
    memset(head,-1,sizeof head);
    tot=0;
}
void add(int u,int v,int c,int w){
    to[tot]=v;
    cap[tot]=c;
    flow[tot]=0;
    cost[tot]=w;
    nxt[tot]=head[u];
    head[u]=tot++;
    swap(u,v);
    to[tot]=v;
    cap[tot]=0;
    flow[tot]=0;
    cost[tot]=-w;
    nxt[tot]=head[u];
    head[u]=tot++;
}
struct QUEUE{
    int que[maxn];
    int front,rear;
    void init(){front=rear=0;}
    void push(int x){que[rear++]=x;}
    int pop(){return que[front++];}
    bool empty(){return front==rear;}
}que;
int n,m,s,t;
int dis[maxn],pre[maxn];
bool vis[maxn];
bool spfa(){
    que.init();
    memset(dis,0x80,sizeof dis);
    memset(vis,0,sizeof vis);
    memset(pre,-1,sizeof pre);
    que.push(s);dis[s]=0;vis[s]=1;
    while(!que.empty()){
        int u = que.pop();
        vis[u]=0;
        for(int i = head[u]; ~i; i = nxt[i]){
            int v=to[i],c=cap[i],f=flow[i],w=cost[i];
            if(c>f&&dis[v]<dis[u]+w){
                dis[v]=dis[u]+w;
                pre[v]=i;
                if(!vis[v]){
                    vis[v]=1;
                    que.push(v);
                }
            }
        }
    }
    if(pre[t]==-1)return 0;
    return 1;
}
int mcmf(){
    int mc=0,mf=0;
    while(spfa()){
        int mn=oo;
        for(int i = pre[t]; ~i; i = pre[to[i^1]]){
            mn=min(mn,cap[i]-flow[i]);
        }
        for(int i = pre[t]; ~i; i = pre[to[i^1]]){
            flow[i]+=mn;
            flow[i^1]-=mn;
            mc+=cost[i]*mn;
        }
        mf+=mn;
    }
    return mc;
}
int n1,n2,n3,a[maxn],b[maxn],atr[maxn],x;
char str[199];
int main(){
    while(scanf("%d%d",&n1,&n2)!=EOF){
        init();
        if(n1<n2){
            n3=n2-n1;
            n=2*n2+2;
            t=n;s=t-1;
        }
        else{
            n3=0;
            n=n1+n2+2;
            t=n;s=n-1;  
        }
        for(int i = 1; i <= n1; i++){
            scanf("%s%d",str,&a[i]); 
            if(str[0]=='A') atr[i]=1;
            else atr[i]=0;
        }
        for(int i = 1; i <= n2; i++){
            scanf("%d",&b[i]);
        }
        if(n3) for(int i = 1; i <= n3; i++){
            atr[i+n1]=1;
            a[i+n1]=0;
        }
        for(int i = 1; i <= n2; i++){
            add(s,i,1,0);
        }
        for(int i = 1; i <= n1+n3; i++){
            add(i+n2,t,1,0);
        }
        for(int i = 1; i <= n2; i++){
            for(int j = 1; j <= n1+n3; j++){
                if(atr[j]==1){
                    if(b[i]>=a[j]){
                        if(a[j]!=-oo) add(i,j+n2,1,b[i]-a[j]);
                        else add(i,j+n2,1,b[i]);
                    }
                    else add(i,j+n2,1,-9999);
                }
                else{
                    if(b[i]>a[j]){
                        add(i,j+n2,1,0);
                    }
                    else add(i,j+n2,1,-9999);
                }
            }
        } 
        printf("%d\n",mcmf());
    }
    return 0;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注