zoukankan      html  css  js  c++  java
  • 洛谷P4013数字梯形问题——网络流24题

    题目:https://www.luogu.org/problemnew/show/P4013

    最大费用最大流裸题;

    注意:在第二种情况中,底层所有点连向汇点的边容量应该为inf,因为可以有多条路径结束在同一个点。(为这个调了半天...)

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    queue<int>q;
    int const MAXN=1605,inf=1e9;
    int n,m,head[MAXN],ct=1,cnt,incf[MAXN],dis[MAXN],pre[MAXN],nd[MAXN],bh[25][45],t;
    bool vis[MAXN];
    struct N{
        int hd,to,next,w,v;
        N(int h=0,int t=0,int n=0,int w=0,int v=0):hd(h),to(t),next(n),w(w),v(v) {}
    }edge[MAXN<<1];
    void add(int x,int y,int w,int v)
    {
        edge[++ct]=N(x,y,head[x],w,v);head[x]=ct;
        edge[++ct]=N(y,x,head[y],-w,0);head[y]=ct;
    }
    void clr()
    {
        ct=1;
        memset(head,0,sizeof head);
    }
    bool spfa()
    {
        memset(pre,0,sizeof pre);
        memset(dis,-3,sizeof dis);
    //    memset(incf,3,sizeof incf);
        while(q.size())q.pop();
        dis[0]=0;vis[0]=1;q.push(0);incf[0]=inf;
        while(q.size())
        {
            int x=q.front();q.pop();
    //        printf("x=%d
    ",x);
    //        cout<<x<<endl;
            vis[x]=0;
            for(int i=head[x];i;i=edge[i].next)
            {
                int u=edge[i].to;
                if(dis[u]<dis[x]+edge[i].w&&edge[i].v)
                {
                    dis[u]=dis[x]+edge[i].w;
                    pre[u]=i;
                    incf[u]=min(incf[x],edge[i].v);
                    if(!vis[u])vis[u]=1,q.push(u);
                }
            }
        }
        return pre[t];
    }
    void mcf()
    {
        long long ans=0;
        while(spfa())
        {
            ans+=incf[t]*dis[t];
    //        cout<<incf[t]<<" "<<dis[t]<<endl;
            for(int i=pre[t];i;i=pre[edge[i].hd])
            {
                edge[i].v-=incf[t];
                edge[i^1].v+=incf[t];
            }
        }
        printf("%lld
    ",ans);
    }
    void cl1()
    {
        clr();
        for(int i=1;i<=n;i++)
            add(0,bh[1][i],0,1);
        for(int i=1;i<m;i++)
            for(int j=1;j<n+i;j++)
            {
                int x=bh[i][j];
                int u1=bh[i+1][j],u2=bh[i+1][j+1];
                add(x+cnt,u1,0,1);
                add(x+cnt,u2,0,1);
                add(x,x+cnt,nd[x],1);
            }
        for(int i=1;i<n+m;i++)
        {
            int x=bh[m][i];
            add(x,x+cnt,nd[x],1);
            add(x+cnt,t,0,1);
        }
        mcf();
    }
    void cl2()
    {
        clr();
        for(int i=1;i<=n;i++)
            add(0,bh[1][i],0,1);//!inf
        for(int i=1;i<m;i++)
            for(int j=1;j<n+i;j++)
            {
                int x=bh[i][j];
                int u1=bh[i+1][j],u2=bh[i+1][j+1];
                add(x+cnt,u1,0,1);
                add(x+cnt,u2,0,1);
                add(x,x+cnt,nd[x],inf);
            }
        for(int i=1;i<n+m;i++)
        {
            int x=bh[m][i];
            add(x,x+cnt,nd[x],inf);
            add(x+cnt,t,0,inf);//inf!!!
        }
        mcf();
    }
    void cl3()
    {
        clr();
        for(int i=1;i<=n;i++)
            add(0,bh[1][i],0,1);//!inf
        for(int i=1;i<m;i++)
            for(int j=1;j<n+i;j++)
            {
                int x=bh[i][j];
                int u1=bh[i+1][j],u2=bh[i+1][j+1];
                add(x+cnt,u1,0,inf);
                add(x+cnt,u2,0,inf);
                add(x,x+cnt,nd[x],inf);
            }
        for(int i=1;i<n+m;i++)
        {
            int x=bh[m][i];
            add(x,x+cnt,nd[x],inf);
            add(x+cnt,t,0,inf);
        }
        mcf();
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
            for(int j=1;j<n+i;j++)
            {
                int x;
                scanf("%d",&x);
                nd[++cnt]=x;
                bh[i][j]=cnt;
            }
        t=2*cnt+1;
        cl1();
        cl2();
        cl3();
        return 0;
    }
  • 相关阅读:
    html 页面打印元素被切割,元素自适应分页
    linux jupyter 安装
    == 与 equals()的区别
    多段图
    数据仓库和ODS 的并行
    Linux下对sh文件的基本操作总结
    linux tr命令详解
    数据仓库分层
    利用SQOOP将数据从数据库导入到HDFS(并行导入,增量导入)
    Etl之HiveSql调优(left join where的位置)
  • 原文地址:https://www.cnblogs.com/Zinn/p/8800902.html
Copyright © 2011-2022 走看看