• [网络流24题-2]运输问题


    运输问题

    《数学一本通》例题。直接最小费用最大流。第二问最大费用最大流可以让费用取反然后跑最小费用最大流。

    之后研究过一下这个问题如果销量和产量不等的话可以建一个辅助点费用为0即可。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<ctime>
    #include<queue>
    #define inf 20021225
    #define maxm 20010
    #define maxn 110
    using namespace std;
    
    struct Edge{int to,lt,f,v;}e[maxm<<1];
    int in[maxn<<1],cnt=1,a[maxn],b[maxn],h[maxn<<1],all;
    int s,t,dis[maxn<<1],tot,ans,c[maxn][maxn],na[maxn],nb[maxn];
    bool iq[maxn<<1],vis[maxn<<1];
    void addedge(int x,int y,int f,int v)
    {
         e[++cnt].to=y;e[cnt].lt=in[x];in[x]=cnt;e[cnt].f=f;e[cnt].v=v;
         e[++cnt].to=x;e[cnt].lt=in[y];in[y]=cnt;e[cnt].f=0;e[cnt].v=-v;
    }
    queue<int> q;
    bool spfa()
    {
        while(!q.empty())	q.pop();
        memset(iq,0,sizeof(iq));
        for(int i=1;i<=tot;i++)	dis[i]=inf;
        dis[t]=0;iq[t]=1;q.push(t);
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int i=in[u];i;i=e[i].lt)
            {
                if(e[i^1].f&&dis[e[i].to]>dis[u]+e[i^1].v)
                {
                    dis[e[i].to]=dis[u]+e[i^1].v;
                    if(!iq[e[i].to])
                    {
                        iq[e[i].to]=1;
                        q.push(e[i].to);
                    }
                }
            }
            iq[u]=0;
        }
        return dis[t]==inf?0:1;
    }
    
    int dfs(int x,int f)
    {
        vis[x]=1;
        if(x==t)
            return f;
        int us=0;
        for(int i=h[x];i;i=e[i].lt)
        {
            int v=e[i].to;
            if(!vis[v]&&e[i].f&&dis[x]==dis[v]+e[i].v)
            {
                int cur=dfs(v,min(f-us,e[i].f));
                if(cur)
                {
                    us+=cur;e[i].f-=us;e[i^1].f+=us;
                    ans+=cur*e[i].v;
                    if(f==us)	return f;
                }
                if(e[i].f)	h[x]=i;
            }
        }
        return us;
    }
    
    void link(int m,int n)
    {
        s=++tot;t=++tot;
        for(int i=1;i<=m;i++)
        {
            na[i]=++tot;
            if(a[i])	addedge(s,na[i],a[i],0);
        }
        for(int i=1;i<=n;i++)
        {
            nb[i]=++tot;
            if(b[i])	addedge(nb[i],t,b[i],0);
        }
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                if(a[i]&&b[j])
                    addedge(na[i],nb[j],inf,c[i][j]);
    }
    
    void flow()
    {
        int f=0;
        while(spfa())
        {
            vis[t]=1;
            memcpy(h,in,sizeof(in));
            while(vis[t])
            {
                memset(vis,0,sizeof(vis));
                f+=dfs(s,inf);
            }
            if(f==all)	break;
        }
        printf("%d
    ",ans<0?-ans:ans);
    }
    
    void clear()
    {
        cnt=1;ans=tot=0;
        memset(in,0,sizeof(in));
        memset(vis,0,sizeof(vis));
    }
    
    int main()
    {
        int n,m,i,j;
        scanf("%d%d",&m,&n);
        for(i=1;i<=m;i++)
            scanf("%d",&a[i]),all+=a[i];
        for(i=1;i<=n;i++)
            scanf("%d",&b[i]);
        for(i=1;i<=m;i++)
            for(j=1;j<=n;j++)
                scanf("%d",&c[i][j]);
        link(m,n);
        flow();
        clear();
        for(i=1;i<=m;i++)
            for(j=1;j<=n;j++)
                c[i][j]=-c[i][j];
        link(m,n);
        flow();
        return 0;
    }
  • 相关阅读:
    怎样练习一万小时
    新闻的未来
    有些人无缘再见,却一生想念
    媒体该如何展示事实之美?
    传统媒体:广告都去哪儿了?
    一线从业者干货分享:不做“忧伤”的媒体人
    整理者与信息平台
    把媒体当手段还是当目的?
    媒体人转身,转身去哪里?
    腾讯新闻的海量服务
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/10321964.html
Copyright © 2020-2023  润新知