• POJ 2195 Going Home


    题目大意:

    给你n个房子和n个人,每个人要住一间房子。每个人到房子有一个距离。求所有人都有房子,并且所走的总距离是最小的。
    ================================================
    二分图KM:
     
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<map>
    using namespace std;
    typedef long long LL;
    const int INF = 1e9+7;
    const int maxn = 105;
    const int MOD = 1e9+7;
    struct node
    {
        int x, y;
        node (int x=0,int y=0): x(x), y(y) {}
    } Man[maxn], House[maxn];
    int Lx[maxn], Ly[maxn], G[maxn][maxn], P[maxn], k, d;///可行性顶标
    bool vx[maxn], vy[maxn];
    char maps[maxn][maxn];
    
    bool Find(int u)
    {
        vx[u] = true;
        for(int i=0; i<k; i++)
        {
            if(!vy[i] && Lx[u] + Ly[i] == G[u][i])
            {
                vy[i] = true;
                if(P[i] == -1 || Find(P[i]) )
                {
                    P[i] = u;
                    return true;
                }
            }
            if(!vy[i])
                d = min(d, Lx[u] + Ly[i] - G[u][i]);
        }
        return false;
    }
    
    int solve()
    {
        memset(P, -1, sizeof(P));
        for(int i=0; i<k; i++)
        {
            while(1)
            {
                memset(vx, false, sizeof(vx));
                memset(vy, false, sizeof(vy));
                d = INF;
                if( Find(i) )
                    break;
    
                for(int j=0; j<k; j++)
                {
                    if(vx[j]) Lx[j] -= d;
                    if(vy[j]) Ly[j] += d;
                }
            }
        }
        int ans = 0;
        for(int i=0; i<k; i++)
            ans += G[P[i]][i];
        return abs(ans);
    }
    
    int Len(node A, node B)
    {
        return  abs(A.x - B.x) + abs(A.y - B.y);
    }
    
    int main()
    {
        int n, m, k1, k2;///n*m的矩阵有k个房子
    
        while(scanf("%d %d",&n, &m), n+m)
        {
            k1 = k2 = 0;
            memset(Lx, 0, sizeof(Lx));
            memset(Ly, 0, sizeof(Ly));
            for(int i=0; i<n; i++)
            {
                scanf("%s", maps[i]);
                for(int j=0; j<m; j++)
                {
                    if(maps[i][j] == 'H')
                        House[k1 ++] = node(i,j);
                    if(maps[i][j] == 'm')
                        Man[k2 ++] = node(i,j);
                }
            }
            k = k1;
            for(int i=0; i<k; i++)
            for(int j=0; j<k; j++)
                G[i][j] = -Len(House[i],Man[j]);
    
            int ans = solve();
            printf("%d
    ", ans);
        }
        return 0;
    }
    /*
    5 5
    HH..m
    .....
    .....
    .....
    mm..H
    
    */

    ===========================================================================================================

    网络流

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<map>
    using namespace std;
    typedef long long LL;
    const int INF = 1e9+7;
    const int maxn = 2005;
    const int MOD = 1e9+7;
    /**最小费用最大流*/
    struct Point
    {
        int x, y;
        Point(int x=0,int y=0): x(x), y(y) {}
    }Man[maxn], House[maxn];
    struct Map
    {
        int flow, cost;
        Map(int flow=0,int cost=0):flow(flow), cost(cost) {}
    }G[maxn][maxn];
    int dist[maxn], Pre[maxn], k;
    bool vis[maxn];
    char maps[maxn][maxn];
    
    int Len(Point A,Point B)
    {
        return abs(A.x-B.x) + abs(A.y-B.y);
    }
    bool Spfa(int Star,int End)
    {
        for(int i=0; i <= End; i++)
            dist[i] = INF;
        dist[Star] = 0;
        memset(Pre, 0, sizeof(Pre));
        memset(vis, false, sizeof(vis));
        queue<int> Q;
        Q.push(Star);
        vis[Star] = true;
        while(Q.size())
        {
            int u = Q.front();
            Q.pop();
            vis[u] = false;
    
            for(int i=0; i<=End; i++)
            {
                if(dist[u]+G[u][i].cost < dist[i] && G[u][i].flow)
                {
                    Pre[i] = u;
    
                    dist[i] = dist[u]+G[u][i].cost;
                    if(!vis[i])
                    {
                        vis[i] = true;
                        Q.push(i);
                    }
    
                }
            }
        }
        return dist[End] != INF;
    }
    
    int solve(int Star,int End)
    {
        int cost = 0;
    
        while( Spfa(Star, End) )
        {
            for(int i=End; i!= Star; i=Pre[i])
            {
                cost += G[Pre[i]][i].cost;
                G[Pre[i]][i].flow -= 1;
                G[i][Pre[i]].flow += 1;
            }
        }
        return cost;
    }
    
    int main()
    {
        int n, m;
        while(scanf("%d %d",&n, &m),n+m)
        {
            memset(G, 0,sizeof(G));
            int k1 = 0, k2 = 0;
            for(int i=0; i<n; i++)
            {
                scanf("%s", maps[i]);
                for(int j=0; j<m; j++)
                {
                    if(maps[i][j] == 'H')
                        House[k1++] = Point(i,j);
                    if(maps[i][j] == 'm')
                        Man[k2++] = Point(i,j);
                }
            }
            int Star = 0, End = 2*k1+1;
    
            for(int i=1; i<=k1; i++)///建立源点到人的边
                G[0][i] = Map(1, 0);
    
            for(int i=1; i<=k1; i++)///建立人到房子
            for(int j=k1+1; j<=2*k1; j++)
            {
                G[i][j] = Map(1, Len(Man[i-1], House[j-k1-1]));
                G[j][i].cost = -G[i][j].cost;
            }
    
    
            for(int i=k1+1; i<=2*k1; i++)///建立房子到汇点的边
                G[i][End] = Map(1, 0);
    
            printf("%d
    ", solve(Star, End));
    
        }
        return 0;
    }
  • 相关阅读:
    实验5 Spark SQL 编程初级实践
    豆瓣基础架构
    淘宝数据魔方技术架构解析
    质量属性的六个常见属性场景--淘宝网
    Win10家庭版WindowsUpdate属性为灰色
    豆瓣的基础架构
    京东618实践:一元抢宝系统的数据库架构优化
    FunData — 电竞大数据系统架构演进
    Ubuntu14.0使用gparted调整分区大小
    二阶段开发冲刺一
  • 原文地址:https://www.cnblogs.com/chenchengxun/p/4860551.html
Copyright © 2020-2023  润新知