• POJ2195费用流+BFS建图


    题意:
          给你一个n*m的地图,上面有w个人,和w个房子,每个人都要进房子,每个房子只能进一个人,问所有人都进房子的路径总和最少是多少?


    思路:
          比较简单的最大流,直接建立两排,左边人,右边房子,广搜或者深搜求距离建图,然后一边费用流就行了,比较简单,没啥说的地方,就这样。
       


    #include<queue>
    #include<stdio.h>
    #include<string.h>


    #define N_node 200 + 10
    #define N_edge (200 * 200 + 200 ) * 2 + 100
    #define INF 1000000000


    using namespace std;


    typedef struct
    {
        int from ,to ,cost ,flow ,next;
    }STAR;


    typedef struct
    {
        int x ,y ,t;
    }NODE;


    STAR E[N_edge];
    NODE xin ,tou;
    int list[N_node] ,tot;
    int s_x[N_node];
    int mer[N_node];
    int map[102][102] ,n ,m;
    int dir[4][2] = {0 ,1 ,0 ,-1 ,1 ,0 ,-1 ,0};


    void add(int a ,int b ,int c ,int d)
    {
        E[++tot].from = a;
        E[tot].to = b;
        E[tot].cost = c;
        E[tot].flow = d;
        E[tot].next = list[a];
        list[a] = tot;




        E[++tot].from = b;
        E[tot].to = a;
        E[tot].cost = -c;
        E[tot].flow = 0;
        E[tot].next = list[b];
        list[b] = tot;
    }


    bool SPFA(int s ,int t ,int n)
    {
        for(int i = 0 ;i <= n ;i ++)
        s_x[i] = INF;
        bool mark[N_node] = {0};
        queue<int>q;
        q.push(s);
        mark[s] = 1;
        s_x[s] = 0;
        memset(mer ,255 ,sizeof(mer));
        while(!q.empty())
        {
            int xin ,tou;
            tou = q.front();
            q.pop();
            mark[tou] = 0;
            for(int k = list[tou] ;k ;k = E[k].next)
            {
                xin = E[k].to;
                if(s_x[xin] > s_x[tou] + E[k].cost && E[k].flow)
                {
                    s_x[xin] = s_x[tou] + E[k].cost;
                    mer[xin] = k;
                    if(!mark[xin])
                    {
                        mark[xin] = 1;
                        q.push(xin);
                    }
                }
            }
        }
        return mer[t] != -1;
    }




    int M_C_Flow(int s ,int t ,int n)
    {
        int mincost = 0 ,maxflow = 0 ,minflow;
        while(SPFA(s ,t ,n))
        {
            minflow = INF;
            for(int i = mer[t] ;i + 1 ;i = mer[E[i].from])
            if(minflow > E[i].flow) minflow = E[i].flow;
            for(int i = mer[t] ;i + 1 ;i = mer[E[i].from])
            {
                E[i].flow -= minflow;
                E[i^1].flow += minflow;
                mincost += E[i].cost;
            }
            maxflow += minflow;
        }
        return mincost;
    }




    void BFS_Buid(int x ,int y ,int N)
    {
        xin.x = x ,xin.y = y ,xin.t = 0;
        int mark[105][105] = {0};
        queue<NODE>q;
        mark[x][y] = 1;
        q.push(xin);
        while(!q.empty())
        {
            tou = q.front();
            q.pop();
            if(map[tou.x][tou.y] > N)
            add(map[x][y] ,map[tou.x][tou.y] ,tou.t ,INF);
            for(int i = 0 ;i < 4 ;i ++)
            {
                xin.x = tou.x + dir[i][0];
                xin.y = tou.y + dir[i][1];
                xin.t = tou.t + 1;
                if(xin.x >= 1 && xin.x <= n && xin.y >= 1 && xin.y <= m && !mark[xin.x][xin.y])
                {
                    mark[xin.x][xin.y] = 1;
                    q.push(xin);
                }
            }
        }
        return ;
    }


    int main ()
    {
        int i ,j;
        char str[105][105];
        while(~scanf("%d %d" ,&n ,&m) && n + m)
        {
            int M = 0 ,H = 0 ,N = 0;
            for(i = 1 ;i <= n ;i ++)
            {
                scanf("%s" ,str[i]);
                for(j = 0 ;j < m ;j ++)
                if(str[i][j] == 'm')
                N ++;
            }
            for(i = 1 ;i <= n ;i ++)
            {
                for(j = 1 ;j <= m ;j ++)
                {
                    if(str[i][j-1] == '.') map[i][j] = 0;
                    else if(str[i][j-1] == 'm') map[i][j] = ++M;
                    else
                    {
                        ++H;
                        map[i][j] = H + N;
                    }
                }
            }
            memset(list ,0 ,sizeof(list)) ,tot = 1;
            for(i = 1 ;i <= N ;i ++)
            add(0 ,i ,0 ,1) ,add(i + N ,N + N + 1 ,0 ,1);
            for(i = 1 ;i <= n ;i ++)
            for(j = 1 ;j <= m ;j ++)
            {
                if(map[i][j] && map[i][j] <= N)
                BFS_Buid(i ,j ,N);
            }
            printf("%d " ,M_C_Flow(0 ,N + N + 1 ,N + N + 1));
        }
        return 0;
    }































  • 相关阅读:
    Spring Boot分布式系统实践【扩展1】shiro+redis实现session共享、simplesession反序列化失败的问题定位及反思改进
    Spring Boot分布式系统实践【2】框架搭建
    javascript日期比较 js日期相差天数计算
    SyntaxHighlighter_代码高亮插件
    CSS控制div自动延伸到窗口100%高度
    iphone天气插件weathericon,安装,及其解决天气不变的方法!亲测!
    Zapatec.Calendar 说明文档
    html设置多少秒跳转
    CSS命名规范
    解决firefox的button按钮文字不能垂直居中
  • 原文地址:https://www.cnblogs.com/csnd/p/12062472.html
Copyright © 2020-2023  润新知