• luogu P4013 数字梯形问题 网络流24 最大费用最大流


    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<iostream>
    using namespace std;
    const int maxn=100010;
    bool vis[maxn];
    int n,m,s,t,x,y,z,f,cost[maxn],pre[maxn],last[maxn],flow[maxn],maxflow,mincost;
    //cost最小花费;pre每个点的前驱;last每个点的所连的前一条边;flow源点到此处的流量
    //maxflow 最大流量
    //mincost 最大流量的情况下的最小花费
    struct Edge
    {
        int to,next,flow,cost;//flow流量 cost花费
    } edge[maxn];
    int head[maxn],num_edge;
    queue <int> q;
    int mp[1001][1001],id[1001][1001],cnt;
    const int inf=0x3f3f3f3f;
    void add(int from,int to,int flow,int cost)
    {
        edge[++num_edge].next=head[from];
        edge[num_edge].to=to;
        edge[num_edge].flow=flow;
        edge[num_edge].cost=cost;
        head[from]=num_edge;
    
        edge[++num_edge].next=head[to];
        edge[num_edge].to=from;
        edge[num_edge].flow=0;
        edge[num_edge].cost=-cost;
        head[to]=num_edge;
    }
    bool spfa(int s,int t)
    {
        memset(cost,0x3f,sizeof(cost));
        memset(flow,0x3f,sizeof(flow));
        memset(vis,0,sizeof(vis));
        q.push(s);
        vis[s]=1;
        cost[s]=0;
        pre[t]=-1;
        while (!q.empty())
        {
            int now=q.front();
            q.pop();
            vis[now]=0;
            for (int i=head[now]; i!=-1; i=edge[i].next)
            {
                if (edge[i].flow>0 && cost[edge[i].to]>cost[now]+edge[i].cost)//正边
                {
                    cost[edge[i].to]=cost[now]+edge[i].cost;
                    pre[edge[i].to]=now;
                    last[edge[i].to]=i;
                    flow[edge[i].to]=min(flow[now],edge[i].flow);//
                    if (!vis[edge[i].to])
                    {
                        vis[edge[i].to]=1;
                        q.push(edge[i].to);
                    }
                }
            }
        }
        return pre[t]!=-1;
    }
    
    void MCMF()
    {
        while (spfa(s,t))
        {
            int now=t;
            maxflow+=flow[t];
            mincost+=cost[t]*flow[t];
            while (now!=s)
            {
                //从源点一直回溯到汇点
                edge[last[now]].flow-=flow[t];//flow和cost容易搞混
                edge[last[now]^1].flow+=flow[t];
                now=pre[now];
            }
        }
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        num_edge=1;
        cin>>n>>m;
        cnt=1;
        for(int i=1; i<=m; i++)
            for(int j=1; j<=n+i-1; j++)
            {
                cin>>mp[i][j];
                id[i][j]=++cnt;
            }
        s=0,t=1;
        int T=cnt;
        for(int i=1; i<=m; i++)
            for(int j=1; j<=n+i-1; j++)
            {
                add(id[i][j],id[i][j]+T,1,-mp[i][j]);//建反向的 
                if(i==m)
                    continue;
                add(id[i][j]+T,id[i+1][j],1,0);
                add(id[i][j]+T,id[i+1][j+1],1,0);
            }
        for(int i=1; i<=n; i++)
            add(s,id[1][i],1,0);
        for(int i=1; i<=n+m-1; i++)
            add(id[m][i]+T,t,1,0);
        MCMF();
        cout<<-mincost<<endl;//输出负数 
        for(int i=2; i<=num_edge; i+=2)
            edge[i].flow+=edge[i^1].flow,edge[i^1].flow=0;
        maxflow=mincost=0;
        for(int i=1; i<=m; i++)
            for(int j=1; j<=n+i-1; j++)
            {
                add(id[i][j],id[i][j]+T,inf,-mp[i][j]);
            }
        for(int i=1; i<=n+m-1; i++)
            add(id[m][i]+T,t,inf,0);
        MCMF();
        cout<<-mincost<<endl;
        for(int i=2; i<=num_edge; i+=2)
            edge[i].flow+=edge[i^1].flow,edge[i^1].flow=0;
        maxflow=mincost=0;
        for(int i=1; i<=m-1; i++)
            for(int j=1; j<=n+i-1; j++)
            {
                add(id[i][j]+T,id[i+1][j],inf,0);
                add(id[i][j]+T,id[i+1][j+1],inf,0);
            }
        MCMF();
        cout<<-mincost<<endl;
        return 0;
    }
  • 相关阅读:
    mysql 存储过程实例
    国际会议查询方式和相关会议
    用 WEKA 进行数据挖掘,第 1 部分: 简介和回归(转)
    java实现甘特图的2种方法:SwiftGantt和Jfree (转)
    通过jxl 读取excel 文件中的日期,并计算时间间隔
    R 操作矩阵和计算SVD的基本操作记录
    SVD java 算法实现
    聚类方法简介
    Kolmogorov-Smirnov检验
    Java Thread 多线程 介绍
  • 原文地址:https://www.cnblogs.com/QingyuYYYYY/p/13179510.html
Copyright © 2020-2023  润新知