• [网络流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;
    }
  • 相关阅读:
    HDU 2822 Dogs【两次bfs】
    HDU 2819 Swap【二分图|启发题】
    HDU 2818 Building Block【并查集+根节点偏移量】
    HDU 2817 A sequence of numbers【水题|快速幂】
    Linux内核分析--操作系统是如何工作的
    讲座感想
    用eclipse开发和调试postgresql-8.4.1
    Ubuntu 14.04下翻译软件的安装与比较
    Linux下autoconf和automake使用
    github 使用网址
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/10321964.html
Copyright © 2020-2023  润新知