zoukankan      html  css  js  c++  java
  • 网络流之最小费用最大流

    题目链接:https://cn.vjudge.net/contest/68128#problem/D

    具体思路:建好图之后,每一次从源点到汇点走最短路,如果能走到就加上,如果走不到就停止。具体注意细节在代码中解释。

    AC代码:

    #include<iostream>
    #include<string>
    #include<cstring>
    #include<iomanip>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<queue>
    #include<stack>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    # define inf 0x3f3f3f3f
    # define ll long long
    # define maxn 100000+10
    struct point
    {
        int x,y;
    } H[maxn],M[maxn];
    char str[100][100];
    int head[maxn];//前向星的建立。
    int num;
    int pree[maxn];//记录该点前一个连的点。
    int prev[maxn];//记录该点位于前向星的哪一条边上。
    int vis[maxn];
    int dist[maxn];//记录距离
    struct node
    {
        int to;
        int w;
        int cost;
        int nex;
    } edge[maxn];
    void addage(int fr,int to,int w,int cost)
    {
        edge[num].to=to;
        edge[num].w=w;
        edge[num].cost=cost;
        edge[num].nex=head[fr];
        head[fr]=num++;
        edge[num].to=fr;//反向边的建立,方向相反,流量为0,话费为原来花费的负数。
        edge[num].w=0;
        edge[num].cost=-cost;
        edge[num].nex=head[to];
        head[to]=num++;
    }
    bool spfa(int st,int ed)
    {
        memset(vis,0,sizeof(vis));
        memset(dist,inf,sizeof(dist));
        memset(pree,-1,sizeof(pree));
        queue<int>q;
        vis[st]=1;
        dist[st]=0;
        q.push(st);
        while(!q.empty())
        {
            int top=q.front();
            q.pop();
            vis[top]=0;
            for(int i=head[top]; i!=-1; i=edge[i].nex)
            {
                int temp=edge[i].to;
                if(edge[i].w>0&&dist[temp]>dist[top]+edge[i].cost)//求最短路的过程,注意dist数组里存的是花费,不是流量。
                {
                    dist[temp]=dist[top]+edge[i].cost;
                    pree[temp]=top;
                    prev[temp]=i;
                    if(vis[temp]==0)
                    {
                        vis[temp]=1;
                        q.push(temp);
                    }
                }
            }
        }
        return pree[ed]!=-1;
    }
    int mincostflow(int st,int ed)
    {
        int ans=0;
        while(spfa(st,ed))
        {
            int minn=inf;
            for(int i=ed; i!=st; i=pree[i])
            {
                minn=min(minn,edge[prev[i]].w);
            }
            ans+=dist[ed]*minn;
            for(int i=ed; i!=st; i=pree[i])
            {
                edge[prev[i]].w-=minn;
                edge[prev[i]^1].w+=minn;
            }
        }
        return ans;
    }
    int main()
    {
        int n,m;
        while(~scanf("%d%d",&n,&m)&&(m+n))
        {
            num=0;
            memset(head,-1,sizeof(head));
            for(int i=1; i<=n; i++)
            {
                scanf("%s",str[i]+1);
            }
            int t1=0,t2=0;
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=m; j++)
                {
                    if(str[i][j]=='H')
                    {
                        H[++t1].x=i;
                        H[t1].y=j;
                    }
                    else if(str[i][j]=='m')
                    {
                        M[++t2].x=i;
                        M[t2].y=j;
                    }
                }
            }
            for(int i=1; i<=t1; i++)
            {
                for(int j=1; j<=t1; j++)
                {
                    addage(i,t1+j,1,abs(M[i].x-H[j].x)+abs(M[i].y-H[j].y));
                }
            }
            int st=0,ed=t1+t1+1;
            for(int i=1; i<=t1; i++)
            {
                addage(st,i,1,0);//源点到学生流量为1,花费为0
            }
            for(int i=1; i<=t1; i++)
            {
                addage(t1+i,ed,1,0);//同理
            }
            int ans=mincostflow(st,ed);
            printf("%d
    ",ans);
        }
        return 0;
    }
    
    
    
    
  • 相关阅读:
    洛谷 P1443 马的遍历
    括号序列 (自出水题)
    19年清北学堂冬令营游记
    计数排列(模板)
    全排列
    unique去重
    链表 模板+详解
    输入输出优化
    关于广/宽度优先搜索
    第四周 6.7-6.13
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10262840.html
Copyright © 2011-2022 走看看