「网络流24题」 16. 数字梯形问题

「网络流24题」 16. 数字梯形问题

<题目链接>


我没坑网络流 24 题!我来填坑了!

最大费用最大流。

建图麻烦,跑板子简单。

先占着,明天再写题解。

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using std::fill;
using std::max;
using std::min;
using std::queue;
const int MAXN=1200,INF=0x3f3f3f3f;
int m,n,S,T,cnt,a[30][30],num[30][30];
struct Edge
{
    int to,w,f;
    Edge *nxt,*back;
    Edge(int to,int w,int f,Edge* nxt):to(to),w(w),f(f),nxt(nxt),back(nullptr){}
    ~Edge(void)
    {
        if(nxt!=nullptr)
            delete nxt;
    }
}*head[MAXN];
void AddEdges(int u,int v,int w,int f)
{
    head[u]=new Edge(v,w,f,head[u]);
    head[v]=new Edge(u,0,-f,head[v]);
    head[u]->back=head[v];
    head[v]->back=head[u];
}
void Init(void)
{
    for(int i=S;i<=T;++i)
        head[i]=nullptr;
}
void Build(int opt)
{
    Init();
    for(int i=1;i<=m;++i)
        AddEdges(S,num[1][i],1,0);
    for(int i=1;i<n;++i)
        for(int j=1;j<m+i;++j)
            if(opt==1)
            {
                AddEdges(num[i][j],num[i][j]+cnt,1,a[i][j]);
                AddEdges(num[i][j]+cnt,num[i+1][j],1,0);
                AddEdges(num[i][j]+cnt,num[i+1][j+1],1,0);
            }
            else
            {
                bool t=opt==2;
                AddEdges(num[i][j],num[i+1][j],t ? 1 : INF,a[i][j]);
                AddEdges(num[i][j],num[i+1][j+1],t ? 1 : INF,a[i][j]);
            }
    for(int i=1;i<m+n;++i)
        if(opt==1)
        {
            AddEdges(num[n][i],num[n][i]+cnt,1,a[n][i]);
            AddEdges(num[n][i]+cnt,T,1,0);
        }
        else
            AddEdges(num[n][i],T,INF,a[n][i]);
}
void Destroy(void)
{
    for(int i=S;i<=T;++i)
        delete head[i];
}
namespace MCMF
{
    bool exist[MAXN];
    int dis[MAXN],pre[MAXN],flow[MAXN];
    Edge *pre_e[MAXN];
    bool SPFA(int S,int T)
    {
        queue<int> q;
        memset(exist,false,sizeof exist);
        memset(dis,0xc0,sizeof dis);
        memset(pre,0,sizeof pre);
        memset(flow,0x3f,sizeof flow);
        fill(pre_e,pre_e+T+1,nullptr);
        q.push(S);
        exist[S]=1;
        dis[S]=0;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            exist[u]=0;
            for(Edge *i=head[u];i!=nullptr;i=i->nxt)
            {
                int v=i->to;
                if(i->w && dis[v]<dis[u]+i->f)
                {
                    if(!exist[v])
                    {
                        q.push(v);
                        exist[v]=1;
                    }
                    dis[v]=dis[u]+i->f;
                    pre[v]=u;
                    pre_e[v]=i;
                    flow[v]=min(flow[u],i->w);
                }
            }
        }
        return dis[T]!=0xc0c0c0c0;
    }
    void Run(int S,int T)
    {
        int ans=0;
        while(SPFA(S,T))
            for(int i=T;i!=S;i=pre[i])
            {
                Edge *t=pre_e[i];
                t->w-=flow[T];
                t->back->w+=flow[T];
                ans+=t->f*flow[T];
            }
        printf("%d\n",ans);
    }
}
int main(int argc,char** argv)
{
    scanf("%d %d",&m,&n);
    for(int i=1;i<=n;++i)
        for(int j=1;j<m+i;++j)
        {
            scanf("%d",&a[i][j]);
            num[i][j]=++cnt;
        }
    S=0,T=(cnt<<1)+1;
    for(int i=1;i<=3;++i)
    {
        Build(i);
        MCMF::Run(S,T);
        Destroy();
    }
    return 0;
}

谢谢阅读。

猜你喜欢

转载自www.cnblogs.com/Capella/p/9108269.html