洛谷P4016 负载平衡问题(最小费用最大流)

题目描述

GG 公司有 nn 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等。如何用最少搬运量可以使 nn 个仓库的库存数量相同。搬运货物时,只能在相邻的仓库之间搬运。

输入输出格式

输入格式:

文件的第 11 行中有 11 个正整数 nn ,表示有 nn 个仓库。

第 22 行中有 nn 个正整数,表示 nn 个仓库的库存量。

输出格式:

输出最少搬运量。

输入输出样例

输入样例#1: 复制

5
17 9 14 16 4

输出样例#1: 复制

11

说明

1 \leq n \leq 1001≤n≤100

昨天老师讲课的时候总在冥冥之中感觉这题貌似做过,貌似可以用贪心水过去,看了题解发现的确可以用贪心水QWQ....

网络流做法

其实很简单,只是我太菜想的太复杂了QWQ...

从S向每个点连容量为库存量,费用为0的边

从每个点向T连容量为平均库存量,费用为0的边

在相邻两个点之间连容量为INF,费用为1的边

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define AddEdge(x,y,z,f) add_edge(x,y,z,f),add_edge(y,x,-z,0)
using namespace std;
const int INF=1e8+10;
const int MAXN=1e4+10;
int N,M,S,T;
int C[MAXN][MAXN];
struct node
{
    int u,v,w,f,nxt;
}edge[MAXN];
int head[MAXN],num=2;
inline void add_edge(int x,int y,int z,int f)
{
    edge[num].u=x;
    edge[num].v=y;
    edge[num].w=z;
    edge[num].f=f;
    edge[num].nxt=head[x];
    head[x]=num++;
}
int dis[MAXN],vis[MAXN],Pre[MAXN];
bool SPFA()
{
    memset(dis,0xf,sizeof(dis));
    memset(vis,0,sizeof(vis));
    queue<int>q;
    q.push(S);
    dis[S]=0;
    while(q.size()!=0)
    {
        int p=q.front();q.pop();
        vis[p]=0;
        for(int i=head[p];i!=-1;i=edge[i].nxt)
        {
            if(edge[i].f&&dis[edge[i].v]>dis[p]+edge[i].w)
            {
                dis[edge[i].v]=dis[p]+edge[i].w;
                Pre[edge[i].v]=i;
                if(!vis[edge[i].v])
                    vis[edge[i].v]=1,q.push(edge[i].v);
            }
        }
    }
    return dis[T]<INF;
}
int F()
{
    int nowflow=INF;
    for(int now=T;now!=S;now=edge[Pre[now]].u)
        nowflow=min(nowflow,edge[Pre[now]].f);
    for(int now=T;now!=S;now=edge[Pre[now]].u)
        edge[Pre[now]].f-=nowflow,
        edge[Pre[now]^1].f+=nowflow;
    return nowflow*dis[T];
}
void MCMF()
{
    int ans=0;
    while(SPFA())
        ans+=F();
    printf("%d\n",abs(ans));
}
int pre(int i)
{
    if(i!=1) return i-1;
    else return N;
}
int nxt(int i)
{
    if(i!=N) return i+1;
    else return 1;
}
int main()
{
    #ifdef WIN32
    freopen("a.in","r",stdin);
    #endif
    memset(head,-1,sizeof(head));
    scanf("%d",&N);
    int tot=0;
    S=0,T=N+1;
    for(int i=1;i<=N;i++)
    {
        int x;scanf("%d",&x);
        AddEdge(S,i,0,x);
        tot+=x;
    }
    tot=tot/N;
    for(int i=1;i<=N;i++)
        AddEdge(i,T,0,tot);
    for(int i=1;i<=N;i++)
    {
        AddEdge(i,pre(i),1,INF);
        AddEdge(i,nxt(i),1,INF);
    }
    MCMF();
    return 0;
}

原文地址:https://www.cnblogs.com/zwfymqz/p/8544703.html

时间: 2024-11-05 12:27:05

洛谷P4016 负载平衡问题(最小费用最大流)的相关文章

[洛谷3381]【模板】最小费用最大流

思路:最小费用最大流模板题.用EdmondsKarp,增广时使用SPFA求最短路. 1 #include<queue> 2 #include<cstdio> 3 #include<cctype> 4 #include<cstring> 5 inline int getint() { 6 char ch; 7 while(!isdigit(ch=getchar())); 8 int x=ch^'0'; 9 while(isdigit(ch=getchar())

洛谷 P3381 【模板】最小费用最大流

题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行包含四个正整数ui.vi.wi.fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi. 输出格式: 一行,包含两个整数,依次为最大流量和在最大流量情况下的最小费用. 输入输出样例 输入样例#

[洛谷P3381]【模板】最小费用最大流

题目大意:给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 解题思路:最小费用最大流模板.虽说此题最后两个点的时限是1200ms,但我觉得耗时在1000ms以上很不爽,于是对代码进行全面优化.然而最后一个点仍然有1050+ms.最后逼我开大招(代码第一行),瞬间只有不到900ms,大爽. C++ Code: %:pragma GCC optimize("Ofast") #include<cstdio> #in

洛谷 3381 【模板】最小费用最大流

https://www.luogu.org/problem/show?pid=3381 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行包含四个正整数ui.vi.wi.fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi. 输出格式: 一

LiberOJ #6013. 「网络流 24 题」负载平衡 最小费用最大流 供应平衡问题

#6013. 「网络流 24 题」负载平衡 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 G 公司有 n nn 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 n nn 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入格式 文件的第 1 11 行中有 1 11 个正整数 n nn,表示有 n nn 个仓库.第 2 22 行中有 n nn 个

最小费用最大流基础模板(洛谷3381)

如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向P3381 [模板]最小费用最大流边的个数.源点序号.汇点序号. 接下来M行每行包含四个正整数ui.vi.wi.fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi. 输出格式: 一行,包含两个整数,依次为最大流量和在最大流量情况下的最小费用. 输入样例#1:

[CODEVS1916] 负载平衡问题(最小费用最大流)

传送门 输入所有 a[i],求出平均值 sum,每个 a[i] -= sum 那么如果 a[i] > 0,从 s 向 i 连一条容量为 a[i] 费用为 0 的有向边 如果 a[i] < 0,从 i 向 t 连一条容量为 -a[i] 费用为 0 的有向边 每个点 i 和它相邻的两个点连一条容量为 INF 费用为 1 的有向边 求出最小费用最大流即为答案 ——代码 1 #include <queue> 2 #include <cstdio> 3 #include <

洛谷 P4009 汽车加油行驶问题 【最小费用最大流】

分层图,建k层,设(i,j,0)为点(i,j)的满油状态,全图的流量都是1,因为重复走到一个点没有意义.如果当前点是加油站,那么它向它上左的点连费用为a的边,向下右连费用为a+b的边: 否则,这个点的所有层向零层连费用为a+c的边表示建加油站和加油,其他的当前点是加油站的情况连即可,但是不用加a.然后s向(1,1,0)连,(n,n)的所有层向t连,最后跑最小费用最大流. #include<iostream> #include<cstdio> #include<cmath>

洛谷 P4015 运输问题 【最小费用最大流+最大费用最大流】

s向仓库i连ins(s,i,a[i],0),商店向t连ins(i+m,t,b[i],0),商店和仓库之间连ins(i,j+m,inf,c[i][j]).建两次图分别跑最小费用最大流和最大费用最大流即可. #include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; const int N=1000005,inf=1e9; int n,m,h