zoukankan      html  css  js  c++  java
  • poj 2195 最小费用最大流模板

    /*Source Code
    Problem: 2195  User: HEU_daoguang
    Memory: 1172K  Time: 94MS
    Language: G++  Result: Accepted
    Source Code
    */
    #include <iostream>
    #include <stdio.h>
    #include <queue>
    #include <math.h>
    #include <string.h>
    using namespace std;
    #define V 6005
    #define E 10010000
    #define inf 999999999
    int n,m;
    char map[102][102];
    int hp[V][2],mp[V][2];
    
    int vis[V];
    int dist[V];
    int pre[V];
    
    struct Edge{
        int u,v,c,cost,next;
    }edge[E];
    int head[V],cnt;
    void init(){
        cnt=0;
        memset(head,-1,sizeof(head));
    }
    
    void addedge(int u,int v,int c,int cost){
        edge[cnt].u=u;edge[cnt].v=v;edge[cnt].cost=cost;
        edge[cnt].c=c;edge[cnt].next=head[u];head[u]=cnt++;
    
        edge[cnt].u=v;edge[cnt].v=u;edge[cnt].cost=-cost;
        edge[cnt].c=0;edge[cnt].next=head[v];head[v]=cnt++;
    }
    
    bool spfa(int begin,int end){
        int u,v;
        queue<int> q;
    
        for(int i=0;i<=end+2;i++){
            pre[i]=-1;
            vis[i]=0;
            dist[i]=inf;
        }
        vis[begin]=1;
        dist[begin]=0;
        q.push(begin);
    
        while(!q.empty()){
    
            u=q.front();
            q.pop();
            vis[u]=0;
    
            for(int i=head[u];i!=-1;i=edge[i].next){
                if(edge[i].c>0){
                    v=edge[i].v;
                    if(dist[v]>dist[u]+edge[i].cost){
                        dist[v]=dist[u]+edge[i].cost;
                        pre[v]=i;
                        if(!vis[v]){
                            vis[v]=true;
                            q.push(v);
                        }
                    }
                }
            }
    
        }
    
        return dist[end]!=inf;
    }
    
    int MCMF(int begin,int end){
        int ans=0,flow;
        int flow_sum=0;
    
        while(spfa(begin,end)){
    
            flow=inf;
            for(int i=pre[end];i!=-1;i=pre[edge[i].u])
                if(edge[i].c<flow)
                    flow=edge[i].c;
            for(int i=pre[end];i!=-1;i=pre[edge[i].u]){
                edge[i].c-=flow;
                edge[i^1].c+=flow;
            }
            ans+=dist[end]*flow;
            flow_sum+=flow;
    
        }
        return ans;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(scanf("%d%d",&n,&m)!=EOF){
            if(n==0 && m==0) break;
            for(int i=0;i<n;i++){
                scanf("%s",map[i]);
            }
            int hcnt=1,mcnt=1;
            for(int i=0;i<n;i++)
                for(int j=0;j<m;j++){
                    if(map[i][j]=='H'){
                        hp[hcnt][0]=i;
                        hp[hcnt][1]=j;
                        hcnt++;
                    }
                    if(map[i][j]=='m'){
                        mp[mcnt][0]=i;
                        mp[mcnt][1]=j;
                        mcnt++;
                    }
                }
            hcnt--;
            mcnt--;
            init();
            for(int i=1;i<=hcnt;i++){
                addedge(0,i,1,0);
                //addedge(i,0,1,0);
            }
            for(int j=1;j<=mcnt;j++){
                addedge(hcnt+j,hcnt+mcnt+1,1,0);
                //addedge(hcnt+mcnt+1,hcnt+j,1,0);
            }
            for(int i=1;i<=hcnt;i++)
                for(int j=1;j<=mcnt;j++){
                    addedge(i,hcnt+j,1,fabs(hp[i][0]-mp[j][0])+fabs(hp[i][1]-mp[j][1]));
                    //addedge(hcnt+j,i,1,fabs(hp[i][0]-mp[j][0])+fabs(hp[i][1]-mp[j][1]));
                }
            int res=MCMF(0,hcnt+mcnt+1);
            printf("%d
    ",res);
        }
        return 0;
    }
    /*
    2
    .m
    H.
    5
    HH..m
    .....
    .....
    .....
    mm..H
    8
    ...H....
    ...H....
    ...H....
    mmmHmmmm
    ...H....
    ...H....
    ...H....
    20
    ..mm..H..H.H...HHH.m
    m.H...H.....H......m
    ..H...mm.........m..
    Hm.m..H.H...H..m....
    mH.Hm....mH........H
    m............m......
    .m..H...........H..m
    H.m.H.....H.......m.
    ...m..Hm.....m.H...H
    ..H...H....H......mH
    ..m.m.....m....mm...
    ..........H.......H.
    ...mm......m...H....
    .....m..H.H......m.m
    .H......mm.H.m.m.m.m
    HH..........HH..HH..
    ...m..H........Hm...
    ....H.....H...mHm...
    H...........m......m
    ....m...H.m.....m...
    20
    ...Hm.m.HHH...Hmm...
    .H........m.......H.
    .......H...H.H......
    ....HmH.m....Hm..m..
    ....m..m............
    H..H.........m....H.
    .m.H...m...mH.m..H..
    .mH..H.H......m...m.
    ...mH...H.......m...
    ..Hm..H..H......m.m.
    ..mH...H.m..m.H..HH.
    m.m......m........m.
    ...mH..m.....mH.....
    ....m.H.H..........H
    ....H.......H....m.H
    H.mH.......m.......H
    ..............m.HH.H
    ..H.........m.m.m...
    .........mH.....mmm.
    ...mH.m.m.....H..m..
    20
    H.H.......H....m....
    .....m..H......H..H.
    ...H..............m.
    mH..mm..m...H.......
    ......H....mm.H.....
    .mH..mm.....mH.H...H
    .........HHH........
    ......H.H...mm......
    .m..m.H...mHmm...HH.
    mm..Hmm.H..m...m.H.m
    H.Hm.m.m.....m......
    ...........m.......H
    ......m......H...m..
    ....H..........Hm...
    .H..H.m....m........
    ...H....Hm..........
    m.H.mHm.m.m...H...H.
    .m..........m.......
    H......H...HmHHm..H.
    ..H..m.m...m.H..H...
    20
    .m..m..Hm...........
    .m..H.H...m.m.m...H.
    ........m..mH....H..
    ..H...........Hm.H.m
    H..H.m........mm..m.
    H.......m...........
    ..m..Hmmmm...m..mH..
    ..H.Hm...H..........
    H....m.......mm.....
    ....m..m.....m.....m
    .H.m.H...H.....H....
    .m........mm..H...H.
    ..m.......H.mH..mm.H
    .......Hm...HH....H.
    ...mm....HHH........
    ..H.m..H........m...
    H.........H.........
    HH.H.....m.H..Hm....
    ...H.m...H.Hm.....m.
    .H..mH..H..H........
    20
    m.........m.......m.
    ..m.H....m....m...m.
    m...H.m.....H.H.....
    .....H.Hm.m...m.....
    ..mH...H.H.m.H...H..
    H....H......m.....m.
    ..................H.
    .m..m.Hm......m..H..
    ....H..H.m.....H...H
    ....m.H......m.H...m
    ....HH...H...H......
    ..H.....m......H.H..
    mmH...mmm.....m.....
    ..m.......m...mmH...
    ......H.H..m...Hm..H
    HHHm.H.m........H...
    ...mHm.......m....m.
    .....mmH.H..H.....m.
    ......m..H.....m...H
    ..HH..m...mH......H.
    20
    m.HHm..HH..m.mHm....
    mm..H...............
    m...HH.......m.H....
    ..mH.m.m.......mmH..
    H.m........m.......H
    m.H....m....m..m...H
    ....m......mm.......
    .m.H....m..H..m..H..
    H....m......H.......
    ...H...........m.m.H
    ......H...m...H..m..
    .mH..H.H.....m......
    ...m.....m.H...HmH.H
    m.......H..H.H..mm.H
    ...H.........Hm.HH..
    .m....H.....m.HHm...
    ...HHH...........m..
    m............H......
    .....m..mm.....m....
    .....m..H..H..H....H
    20
    ....H.............m.
    .....HH..mH..Hm..H..
    m...........mH....mm
    ..m..m.H......m....m
    .H..........mHH....m
    ...........m..H.m...
    ..H...H.........mHm.
    ......H...........H.
    H.....H.....H..m....
    H.H..H..m...m..mH.m.
    ....H...m.H.mHmm.mHm
    ..mmm...H....m....H.
    .........m..m.......
    .m.H....Hm....m.....
    .....H.......HH...mH
    ..H..H....m.m.....HH
    .Hm.............H...
    H...Hm.......H.m.m..
    .....m..HH...H.....m
    ........mHmmH..m....
    20
    .....H.......H...m.m
    .m..H.m.m....m......
    m.H.HHH..mm.........
    H...mH.mH...........
    ..mHm..m.m......m..m
    H.HH.....m...m......
    H.mH....H......H....
    ...mH.m.mHmH...H....
    ........H.....m.....
    ..H.......HmH...H...
    ......m...HH.m......
    .H..m.H...H.........
    ...H...m..m..m...m..
    .mH..HH......m...H..
    
    ...m....H.H.H.m.....
    .........H.m........
    ..m..H...H......H...
    mmH..mH.....m.H..H..
    H....mm...H.m...m.mm
    ......m.............
    20
    ....mH..m...m.....m.
    ..m......mHm...H....
    .H.....mHm....H..H..
    ...HH..........m.m..
    ..m..mm........m....
    ...m.....H..........
    ..mH..H...m.........
    ...H.H.....m..mH..m.
    ..H.........Hm.Hm..H
    ...........H......m.
    .............H...mm.
    H.m.....Hm.H.m......
    ....Hm..m..mm.H...m.
    ...H.H.H......H.Hm..
    H.m............m....
    ..mH.m.m...m..H.m..H
    HH.H....m.H..H...m..
    .....H.....H...H...H
    ........mH.HHm.....m
    .H.H.....mmH......m.
    20
    .mH........m.mmH..H.
    m....H........H..H..
    .........Hm.m.m.....
    ....H.H...m.........
    .H....m.............
    HH.....H.....H.HH...
    mmmmmm.H..m..m......
    .Hm.H...H.H..m.H....
    .........m..m.mHmHH.
    ...m.m....m..H.Hm..H
    ...Hm....H..m....m..
    ...mH.....m.......m.
    .H...HmmH..H.....H..
    m.H...m.....mmH....H
    .m.H......m...H.....
    H........m..Hm......
    .......m...........m
    ...m........m...H...
    .........m...H......
    HH..H..m...H......H.
    */

     上面的网上大牛的代码,我看的好像和我的模板差不多,还有测试样例,我就复了一下,下面的是我的代码

    Going Home
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 19827   Accepted: 10080

    Description

    On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertically, to an adjacent point. For each little man, you need to pay a $1 travel fee for every step he moves, until he enters a house. The task is complicated with the restriction that each house can accommodate only one little man.

    Your task is to compute the minimum amount of money you need to pay in order to send these n little men into those n different houses. The input is a map of the scenario, a '.' means an empty space, an 'H' represents a house on that point, and am 'm' indicates there is a little man on that point.

    You can think of each point on the grid map as a quite large square, so it can hold n little men at the same time; also, it is okay if a little man steps on a grid with a house without entering that house.

    Input

    There are one or more test cases in the input. Each case starts with a line giving two integers N and M, where N is the number of rows of the map, and M is the number of columns. The rest of the input will be N lines describing the map. You may assume both N and M are between 2 and 100, inclusive. There will be the same number of 'H's and 'm's on the map; and there will be at most 100 houses. Input will terminate with 0 0 for N and M.

    Output

    For each test case, output one line with the single integer, which is the minimum amount, in dollars, you need to pay.

    Sample Input

    2 2
    .m
    H.
    5 5
    HH..m
    .....
    .....
    .....
    mm..H
    7 8
    ...H....
    ...H....
    ...H....
    mmmHmmmm
    ...H....
    ...H....
    ...H....
    0 0
    

    Sample Output

    2
    10
    28
    

    Source

     
    求得就是每个人需要到每个房子里,一个房子只能装下一个人,问最少的开销,没走一个单元格的花费就以一元
    可以直接建图,建出每个人到各个房子的距离,连成一条边,流量cap为1,花费cost为dis,即为横坐标的绝对值差加上纵坐标的绝对值差;
    之后建立一个超级原点和一个超级会点,让超级原点连到每一个人,cap为1,cost为0,同理让每一个房子链接到超级汇点,cap为1,cost为0
    之后跑框斌的最小费用最大流算法模板就可以过了,还要注意个问题就是总的点数为cnth+cntm+2
    还有一个需要注意的地方是本题的范围是100*100;
    所以点和边的数值尽量开的大一些
    下面贴上代码
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<math.h>
    #include<vector>
    using namespace std;
    //最小费用最大流,求最大费用只需要取相反数,结果取相反数即可。
    //点的总数为 N,点的编号 0~N-1
    const int MAXN = 6005;
    const int MAXM = 1001000;
    const int INF = 0x3f3f3f3f;
    struct Edge
    {
        int to,next,cap,flow,cost;
    } edge[MAXM];
    int head[MAXN],tol;
    int pre[MAXN],dis[MAXN];
    bool vis[MAXN];
    int N;//节点总个数,节点编号从0~N-1
    void init()
    {
        tol = 0;
        memset(head,-1,sizeof (head));
    }
    void addedge (int u,int v,int cap,int cost){
        edge[tol].to = v;
        edge[tol].cap = cap;
        edge[tol].cost = cost;
        edge[tol].flow = 0;
        edge[tol].next = head[u];
        head[u] = tol++;
        edge[tol].to = u;
        edge[tol].cap = 0;
        edge[tol].cost = -cost;
        edge[tol].flow = 0;
        edge[tol].next = head[v];
        head[v] = tol++;
    }
    bool spfa(int s,int t)
    {
        queue<int>q;
        for(int i = 0; i < N; i++)
        {
            dis[i] = INF;
            vis[i] = false;
            pre[i] = -1;
        }
        dis[s] = 0;
        vis[s] = true;
        q.push(s);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u] = false;
            for(int i = head[u]; i !=  -1; i = edge[i]. next)
            {
                int v = edge[i]. to;
                if(edge[i].cap > edge[i].flow &&
                        dis[v] > dis[u] + edge[i]. cost )
                {
                    dis[v] = dis[u] + edge[i]. cost;
                    pre[v] = i;
                    if(!vis[v])
                    {
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
        }
        if(pre[t] == -1)return false;
        else return true;
    }
    //返回的是最大流,cost存的是最小费用
    int minCostMaxflow(int s,int t,int &cost)
    {
        int flow = 0;
        cost = 0;
        while(spfa(s,t))
        {
            int Min = INF;
            for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
            {
                if(Min > edge[i].cap - edge[i]. flow)
                    Min = edge[i].cap - edge[i].flow;
            }
            for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
            {
                edge[i].flow += Min;
                edge[i^1].flow -= Min;
                cost += edge[i]. cost * Min;
            }
            flow += Min;
        }
        return flow;
    }
    char map[110];
    struct node1{
        int x, y;
    }hh[105];
    struct node2{
         int x,y;
    }mm[105];
    int main(){
       int n,m,sta;
       while(scanf("%d%d",&n,&m)!=EOF){
           if(n==0&&m==0)
           break;
           memset(hh,0,sizeof(hh));
           memset(mm,0,sizeof(mm));
           memset(map,0,sizeof(map));
           memset(pre,0,sizeof(pre));
           memset(dis,0,sizeof(dis));
           memset(vis,false,sizeof(vis));
           memset(edge,0,sizeof(edge));
           memset(hh,0,sizeof(hh));
           memset(mm,0,sizeof(mm));
        init();
          int u,v,w;
          int cnth=0,cntm=0;
        for(int i=0;i<n;i++){
           scanf("%s",map);
           for(int j=0;j<m;j++){
               if(map[j]=='H'){
                   hh[++cnth].x=i;
                   hh[cnth].y=j;
               }
               if(map[j]=='m'){
                   mm[++cntm].x=i;
                   mm[cntm].y=j;
               }
           }
        }
        N=cntm+cnth+2;
        for(int i=1;i<=cntm;i++){
            for(int j=1;j<=cnth;j++){
                 addedge(i,j+cntm,1,abs(mm[i].x-hh[j].x)+abs(mm[i].y-hh[j].y));
                 addedge(j+cntm,i,1,abs(mm[i].x-hh[j].x)+abs(mm[i].y-hh[j].y));
            }
        }
        int ans1=0;
        for(int i=1;i<=cntm;i++){
        addedge(0,i,1,0);
        }
        for(int j=cntm+1;j<=cnth+cntm;j++){
            addedge(j,cnth+cntm+1,1,0);
        }
    
          int temp=minCostMaxflow(0,cnth+cntm+1,ans1);
          printf("%d
    ",ans1);
    
       }
    }
  • 相关阅读:
    网络对抗技术 20181216 Exp6 MSF基础应用
    实验一-密码引擎-加密API研究
    网络对抗技术 20181216 Exp5 信息搜集与漏洞扫描
    网络对抗技术 20181216 Exp4 恶意代码分析原理与实践说明
    网络对抗技术 20181216 Exp3 免杀原理与实践
    用Visual Studio 2019 创建C#窗体项目
    EL表达式的学习
    session学习
    mysql+javaWeb+jdbc+tomcat开发中的中文乱码处理
    java集合
  • 原文地址:https://www.cnblogs.com/13224ACMer/p/4787157.html
Copyright © 2011-2022 走看看