洛谷 P4013 数字梯形问题

->题目链接

 

题解:

网络流。

#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#define N 4010
#define inf 1000000000
using namespace std;
int a[N][N],head[N],dis[N],inq[N],fa[N],n,m,num,cnt,S,T;
struct node {
    int u,v,pre,f,w;
} e[N];
void add(int u,int v,int f,int w) {
    e[++cnt].u=u;e[cnt].v=v;
    e[cnt].f=f;e[cnt].w=w;
    e[cnt].pre=head[u];head[u]=cnt;
    e[++cnt].u=v;e[cnt].v=u;
    e[cnt].f=0;e[cnt].w=-w;
    e[cnt].pre=head[v];head[v]=cnt;
}
bool spfa() {
    for(int i=0; i<=T; i++) dis[i]=inf;
    queue<int> q;
    q.push(S);
    inq[S]=1;
    dis[S]=0;
    while(!q.empty()) {
        int u=q.front();
        q.pop();
        inq[u]=0;
        for(int i=head[u]; i; i=e[i].pre)
            if(e[i].f&&dis[e[i].v]>dis[u]+e[i].w) {
                dis[e[i].v]=dis[u]+e[i].w;
                fa[e[i].v]=i;
                if(!inq[e[i].v]) {
                    inq[e[i].v]=1;
                    q.push(e[i].v);
                }
            }
    }
    return dis[T]!=inf;
}
void mincost() {
    int cost=0;
    while(spfa()) {
        int tmp=fa[T],x=inf;
        while(tmp) {
            int u=e[tmp].u;
            x=min(x,e[tmp].f);
            tmp=fa[e[tmp].u];
        }
        tmp=fa[T];
        while(tmp) {
            e[tmp].f-=x;
            e[tmp^1].f+=x;
            tmp=fa[e[tmp].u];
        }
        cost+=x*dis[T];
    }
    printf("%d\n",-cost);
}
int hao(int i,int j) {
    return (m*2+i-2)*(i-1)/2+j;
}
void build1() {
    cnt=1;
    memset(head,0,sizeof(head));
    for(int i=1; i<=m; i++)
        add(S,i,1,-a[1][i]);
    for(int i=1; i<n; i++)
        for(int j=1; j<=m+i-1; j++)
            add(hao(i,j)+num,hao(i+1,j),1,-a[i+1][j]),add(hao(i,j)+num,hao(i+1,j+1),1,-a[i+1][j+1]);
    for(int i=1; i<=m+n-1; i++)
        add(hao(n,i)+num,T,1,0);
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m+i-1; j++)
            add(hao(i,j),hao(i,j)+num,1,0);

}
void build2() {
    cnt=1;
    memset(head,0,sizeof(head));
    for(int i=1; i<=m; i++)
        add(S,i,1,-a[1][i]);
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m+i-1; j++)
            add(hao(i,j),hao(i+1,j),1,-a[i+1][j]),add(hao(i,j),hao(i+1,j+1),1,-a[i+1][j+1]);
    for(int i=1; i<=m+n-1; i++)
        add(hao(n,i),T,inf,0);
}
void build3() {
    cnt=1;
    memset(head,0,sizeof(head));
    for(int i=1; i<=m; i++)
        add(S,i,1,-a[1][i]);
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m+i-1; j++)
            add(hao(i,j),hao(i+1,j),inf,-a[i+1][j]),add(hao(i,j),hao(i+1,j+1),inf,-a[i+1][j+1]);
    for(int i=1; i<=m+n-1; i++)
        add(hao(n,i),T,inf,0);
}
int main() {
    scanf("%d%d",&m,&n);
    num=(m*2+n-1)*n/2;
    S=0;
    T=num*2+1;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m+i-1; j++)
            scanf("%d",&a[i][j]);
    build1();
    mincost();
    build2();
    mincost();
    build3();
    mincost();
    return 0;
}  
AC

我走我的独木桥。

posted @ 2018-08-07 11:18  IXIS  阅读(167)  评论(0编辑  收藏  举报