Chessboard HDU - 6532 (最大費用流)

題意:給你一個棋盤,棋盤上有一些棋子,有一些規定,規定超過多少行或者多少列後只能取不超過k的棋子。

題解:棋盤問題是一個很經典的網絡流問題。

建圖還是比較好想的,但是不會跑最大費用流,賽後補了一下。

但是好像這道題有問題,最大費用最大流也能過。

但是明顯不符合費用最大時流最大。

所以想一下最小費用最大流的做法,首先費用取反,這樣就變成了最小費用,

每次跑一條s到t的最短路,然後減去這條路的流量。這樣保證每次跑出來的最短路是越來越大的。

所以當最短路第一次大於0時,接下來所有的流量的費用都大於0,會使費用變大,所以直接跳出。

建圖的話,感覺類似並查集的思路,我想了一種很low的建法,題解的建法就很優美了,所以又照着題解建了一波。

#include <bits/stdc++.h>
using namespace std;
#define N 4010
#define inf 0x3f3f3f3f
#define go(i,a,b) for(int i=(a);i<=(b);i++)
#define dep(i,a,b) for(int i=(a);i>=(b);i--)
struct no{
    int to,n,cap,flow,cost;
};no d[N*10];
queue<int>q;
int h[N],dp[N],p[N],f[N],in[N], tot,need;
void add(int u,int to,int w,int v){
    //cout<<u<<' '<<to<<' '<<w<<' '<<v<<'+'<<endl;
    d[tot]={to,h[u],w,0,v };h[u]=tot++;
    d[tot]={u,h[to],0,0,-v};h[to]=tot++;
}
bool spfa(int s,int e){
    memset(dp,inf,sizeof(dp));
    memset(p,-1,sizeof(p));
    memset(f,0,sizeof(f));
    q.push(s);dp[s]=0;
    while(!q.empty()){
        int x=q.front();q.pop();
        f[x]=0;
        for(int i=h[x];i!=-1;i=d[i].n){
            int to=d[i].to,cost=d[i].cost;
            if(dp[x]+cost<dp[to]&&d[i].cap>d[i].flow){
                p[to]=i;
                dp[to]=dp[x]+cost;
                if(f[to])continue;
                f[to]=1;
                q.push(to);
            }
        }
    }
    return p[e]!=-1&&dp[e]<0;
}
int Cost = 0, Flow = 0;
int dini(int s,int e){
    while(spfa(s,e)){
        int Min=inf;
        for(int i=p[e];i!=-1;i=p[d[i^1].to])
            Min=min(Min,d[i].cap-d[i].flow);
        for(int i=p[e];i!=-1;i=p[d[i^1].to]){
            d[i].flow+=Min;
            d[i^1].flow-=Min;
            Cost+=d[i].cost*Min;
        }
        Flow+=Min;
    }
}
int discre(int a[],int n){
    sort(a+1,a+n+1);
    //go(i,1,n)cout<<a[i]<<' ';cout<<endl;
    return unique(a+1,a+n+1)-a-1;
}
inline int getdiscre(int a[],int n,int w){
    return lower_bound(a+1,a+n+1,w)-a;
}
int n,m,c_siz,r_siz;
inline int cid(int x){return x; }
inline int rid(int x){return x+c_siz+1; }
char op[10];
int c1[N],c2[N],r1[N],r2[N],id,k,x[N],y[N];
int main()
{
    cin>>n;
    memset(c2,inf,sizeof(c2));
    memset(r2,inf,sizeof(r2));
    memset(h,-1,sizeof(h));
    go(i,1,n)
        scanf("%d%d",&x[i],&y[i]),
        c1[i]=x[i],r1[i]=y[i];
    c_siz=discre(c1,n),r_siz=discre(r1,n);
    go(i,1,n)add(cid(getdiscre(c1,c_siz,x[i])),rid(getdiscre(r1,r_siz,y[i])),1,-i);
    cin>>m;
    go(i,1,m){
        scanf("%s%d%d",op,&id,&k);
        if(op[0]=='C'){
            id=getdiscre(r1,r_siz,id);
            if(id<=r_siz)r2[id]=min(r2[id],k);
        }
        else {
            id=getdiscre(c1,c_siz,id);
            if(id<=c_siz)c2[id]=min(c2[id],k);
        }
    }

    dep(i,c_siz,1)
        add(cid(i-1),cid(i),c2[i],0);
    dep(i,r_siz,1)
        add(rid(i),rid(i-1),r2[i],0);

    dini(0,c_siz+1);
    printf("%d\n",-Cost);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章