码迷,mamicode.com
首页 > 其他好文 > 详细

poj 2195 最小费用最大流模板

时间:2015-09-06 21:44:58      阅读:238      评论:0      收藏:0      [点我收藏+]

标签:

/*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\n",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\n",ans1);

   }
}

 

poj 2195 最小费用最大流模板

标签:

原文地址:http://www.cnblogs.com/13224ACMer/p/4787157.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!