数字梯形问题

https://loj.ac/problem/6010

拆点最大费用最大流

#include <bits/stdc++.h>
using namespace std;
const int maxn = 50;
const int inf = 0x3f3f3f3f3f;
int head[maxn*maxn];
int a[maxn][maxn];
struct edge{
    int v,nex,w,c;
}e[maxn*maxn*100];
int tot;
void addedge(int u,int v,int w,int c){
    e[tot] = (edge){v,head[u],w,c};
    head[u] = tot++;
    e[tot] = (edge){u,head[v],0,-c};
    head[v] = tot++;
}
int vis[maxn*maxn];
int dis[maxn*maxn];
int pre[maxn*maxn];
bool spfa(int S,int T){
    memset(vis,0,sizeof(vis));
    memset(dis,0x3f,sizeof(dis));
    queue<int> q;
    q.push(S);
    vis[S] = 1;
    dis[S] = 0;
    while(!q.empty()){
        int now = q.front();
        q.pop();
        vis[now] = 0;
        for(int i=head[now];i!=-1;i=e[i].nex){
            int v = e[i].v;
            int w = e[i].w;
            int c = e[i].c;
            if(w>0 && dis[v]>dis[now]+c){
                dis[v] = dis[now]+c;
                pre[v] = i;
                if(vis[v]==0) {
                    vis[v] = 1;
                    q.push(v);
                }
            }
        }
    }
    if(dis[T]==0x3f3f3f3f) return false;
    return true;
}
int ed(int S,int T,int &maxflow){
    int flow = 0x3f3f3f3f;
    int p;
    for(int i=T;i!=S;i=e[p^1].v){
        p = pre[i];
        flow = min(flow,e[p].w);
    }
    int ans = 0;
    for(int i=T;i!=S;i=e[p^1].v){
        p = pre[i];
        ans+=flow*e[p].c;
        e[p].w-=flow;
        e[p^1].w+=flow;
    }
    maxflow+=flow;
    return ans;
}
int m,n;
int P(int x,int y){
    return x*(n+m)+y;
}
int Q(int x,int y){
    return x*(n+m)+y+(n+m)*n;
}
void solve1(){
    int S = maxn*maxn-3;
    int T1 = S+1;
    int T2 = T1+1;
    for(int i=0;i<n;i++){
        for(int j=0;j<m+i;j++){
            addedge(P(i,j),Q(i,j),1,0);
            if(i==0) {
                addedge(S,P(i,j),inf,-a[i][j]);
            }else{
                addedge(Q(i-1,j),P(i,j),1,-a[i][j]);
                if(j!=0) {
                    addedge(Q(i-1,j-1),P(i,j),1,-a[i][j]);
                }

            }
        }
    }
    for(int j=0;j<m+n;j++){
        addedge(Q(n-1,j),T1,1,0);
    }
    addedge(T1,T2,m,0);
    int maxflow = 0;
    int ans = 0;
    while(spfa(S,T2)){
        ans+=ed(S,T2,maxflow);
    }
    printf("%d\n",-ans);
}
void solve2(){

    int S = 41*41;
    int T1 = S+1;
    int T2 = T1+1;
    for(int i=0;i<n;i++){
        for(int j=0;j<m+i;j++){
            addedge(P(i,j),Q(i,j),inf,0);
            if(i==0) {
                addedge(S,P(i,j),1,-a[i][j]);
            }else{
                addedge(Q(i-1,j),P(i,j),1,-a[i][j]);
                if(j!=0) {
                    addedge(Q(i-1,j-1),P(i,j),1,-a[i][j]);
                }

            }
        }
    }
    for(int j=0;j<m+n;j++){
        addedge(Q(n-1,j),T1,inf,0);
    }
    addedge(T1,T2,m,0);
    int maxflow = 0;
    int ans = 0;
    while(spfa(S,T2)){
        ans+=ed(S,T2,maxflow);
    }
    printf("%d\n",-ans);
}
void solve3(){

    int S = 41*41;
    int T1 = S+1;
    int T2 = T1+1;
    for(int i=0;i<n;i++){
        for(int j=0;j<m+i;j++){
            addedge(P(i,j),Q(i,j),inf,0);
            if(i==0) {
                addedge(S,P(i,j),1,-a[i][j]);
            }else{
                addedge(Q(i-1,j),P(i,j),inf,-a[i][j]);
                if(j!=0) {
                    addedge(Q(i-1,j-1),P(i,j),inf,-a[i][j]);
                }

            }
        }
    }
    for(int j=0;j<m+n;j++){
        addedge(Q(n-1,j),T1,inf,0);
    }
    addedge(T1,T2,m,0);
    int maxflow = 0;
    int ans = 0;
    while(spfa(S,T2)){
        ans+=ed(S,T2,maxflow);
    }
    printf("%d\n",-ans);
}
int main()
{
    memset(head,-1,sizeof(head));
    tot = 0;

    scanf("%d%d",&m,&n);
    for(int i=0;i<n;i++){
        for(int j=0;j<m+i;j++){
            scanf("%d",&a[i][j]);
        }
    }
    solve1();
    memset(head,-1,sizeof(head));
    tot = 0;
    solve2();
    memset(head,-1,sizeof(head));
    tot = 0;
    solve3();
    return 0;
}

  

posted @ 2018-03-28 21:24  tjucxz  阅读(150)  评论(0编辑  收藏  举报