• 最小费用流(km的另一种使用思路)


    题目链接:https://cn.vjudge.net/contest/242366#problem/L

    大体意思就是:h代表旅馆,m代表人,人每走动一个需要一个金币,行动只有两个方向,水平或者竖直。问你最终让所有人都能到达旅馆并且花的总费用最少。

    具体思路:一开始我是按照km的初级使用进行敲的,结果发现第二组样例过不了,然后km也打的没问题,看了网上的代码,才发现自己的思路错了。这个题的目的是让你花费最小,而km的初级使用是让总费用最低,如果按照一开始的打的话,就南辕北辙了。

    但是,花费最小的话,只需要存值的时候把原来的任意两个人和旅馆之间距离赋为负值就可以了。

    具体原因:本来km求的是最大值,如果给他加上一个负号,求的也是最大值,相应的变为原来的最小值了(很巧妙)

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    # define maxn 100+10
    # define inf 0x3f3f3f3f
    int n,m;
    char a[maxn][maxn];
    int  dis[maxn][maxn];
    int nx[maxn*maxn],ny[maxn*maxn];
    int visx[maxn*maxn],visy[maxn*maxn];
    int slack[maxn*maxn];
    int net[maxn*maxn];
    int t1,t2;
    struct node
    {
        int x,y;
        node() {}
        node (int xx,int yy)
        {
            x=xx;
            y=yy;
        }
    } Pro[maxn*maxn],Hou[maxn*maxn];
    void init1()
    {
        for(int i=1; i<=t1; i++)
        {
            nx[i]=-inf;
        }
        memset(ny,0,sizeof(ny));
        memset(dis,0,sizeof(dis));
        memset(net,0,sizeof(net));
    }
    void init2()
    {
        memset(visx,0,sizeof(visx));
        memset(visy,0,sizeof(visy));
    }
    bool Find(int t)
    {
        visx[t]=1;
        for(int i=1; i<=t1; i++)
        {
            int temp=nx[t]+ny[i]-dis[t][i];
            if(temp==0)
            {
                if(visy[i]==0)
                {
                    visy[i]=1;
                    if(net[i]==0||Find(net[i]))
                    {
                        net[i]=t;
                        return true;
                    }
                }
            }
            else slack[i]=min(temp,slack[i]);
        }
        return false;
    }
    int km()
    {
        for(int i=1; i<=t1; i++)
        {
            memset(slack,inf,sizeof(slack));
            while(1)
            {
                init2();
                if(Find(i))break;
                int minn=inf;
                for(int i=1; i<=t1; i++)
                {
                    if(!visy[i])
                    {
                        minn=min(minn,slack[i]);
                    }
                }
                for(int i=1; i<=t1; i++)
                {
                    if(visx[i])
                    {
                        nx[i]-=minn;
                    }
                }
                for(int i=1; i<=t2; i++)
                {
                    if(visy[i])
                    {
                        ny[i]+=minn;
                    }
                }
            }
        }
        int sum=0;
        for(int i=1; i<=t1; i++)
        {
            if(net[i])
            {
                sum+=dis[net[i]][i];
            }
        }
        return sum;
    }
    
    int main()
    {
        while(cin>>n>>m&&(n+m))
        {
            init1();
            t1=0,t2=0;
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=m; j++)
                {
                    cin>>a[i][j];
                    if(a[i][j]=='m')
                    {
                        Pro[++t1].x=i;
                        Pro[t1].y=j;
                    }
                    else if(a[i][j]=='H')
                    {
                        Hou[++t2].x=i;
                        Hou[t2].y=j;
                    }
                }
            }
            for(int i=1; i<=t1; i++)
            {
                for(int j=1; j<=t2; j++)
                {
                    dis[i][j]=-(abs(Pro[i].x-Hou[j].x)+abs(Pro[i].y-Hou[j].y));
                    nx[i]=max(nx[i],dis[i][j]);
                }
            }
            int t=km();
            cout<<-t<<endl;
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    高精度
    欢迎来到我的博客!
    1
    POJ 2774 求两个串的最长公共前缀 | 后缀数组
    ural1297 求最长回文子串 | 后缀数组
    洛谷 [SCOI2010]股票交易 | 单调性DP
    BZOJ 1096: [ZJOI2007]仓库建设 | 斜率优化DP
    洛谷 P2906 [USACO08OPEN]牛的街区Cow Neighborhoods | Set+并查集
    BZOJ 1010: [HNOI2008]玩具装箱toy | 单调队列优化DP
    BZOJ 1342: [Baltic2007]Sound静音问题 | 单调队列维护的好题
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10262963.html
Copyright © 2020-2023  润新知