POJ2195 最小费用流

题目:http://poj.org/problem?id=2195

处理出每个人到每个门的曼哈顿距离,分别建立容量为1费用为曼哈顿距离的边,在源点和每个人人之间建立容量为1费用为0的边,在门和汇点之间建立容量为1费用为0的边,然后跑最小费用流即可。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<vector>
 4 #include<queue>
 5 #include<iostream>
 6 #include<stdlib.h>
 7 using namespace std;
 8 typedef pair<int,int> P;
 9 const int maxv = 222;
10 const int inf = 0x3f3f3f3f;
11 struct edge{
12     int to,cap,cost,rev;
13 };
14 int V;
15 vector<edge> g[maxv];
16 int h[maxv];
17 int dist[maxv];
18 int prevv[maxv],preve[maxv];
19 void addedge(int from,int to,int cap,int cost){
20     edge t;
21     t.to = to;t.cap = cap;t.cost = cost;t.rev = g[to].size();
22     g[from].push_back(t);
23     t.to = from;t.cap = 0;t.cost = -cost;t.rev = g[from].size()-1;
24     g[to].push_back(t);
25 }
26 int solve(int s,int t,int f){
27     int res = 0;
28     memset(h,0,sizeof(h));
29     while(f > 0){
30         priority_queue<P,vector<P>,greater<P> > que;
31         memset(dist,inf,sizeof(dist));
32         dist[s] = 0;
33         que.push(P(0,s));
34         while(!que.empty()){
35             P p = que.top();
36             que.pop();
37             int v = p.second;
38             if(dist[v] < p.first)
39                 continue;
40             for(int i = 0;i<g[v].size();i++){
41                 edge &e = g[v][i];
42                 if(e.cap>0 && dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]){
43                     dist[e.to] = dist[v]+e.cost+h[v]-h[e.to];
44                     prevv[e.to] = v;
45                     preve[e.to] = i;
46                     que.push(P(dist[e.to],e.to));
47                 }
48             }
49         }
50         if(dist[t] == inf){
51             return -1;
52         }
53         for(int i = 0;i<=t;i++)
54             h[i] += dist[i];
55         int d = f;
56         for(int i = t;i!=s;i = prevv[i]){
57             d = min(d,g[prevv[i]][preve[i]].cap);
58         }
59         f -= d;
60         res += d*h[t];
61         for(int i = t;i!=s;i = prevv[i]){
62             edge &e = g[prevv[i]][preve[i]];
63             e.cap -= d;
64             g[i][e.rev].cap += d;
65         }
66     }
67     return res;
68 }
69 int main(){
70     int n,m;
71     while(scanf("%d%d",&n,&m) && n && m){
72         vector<P> mm,hh;
73         char ch;
74         for(int i = 1;i<=n;i++){
75             for(int j = 1;j<=m;j++){
76                 scanf(" %c",&ch);
77                 if(ch == ‘m‘)
78                     mm.push_back(P(i,j));
79                 if(ch == ‘H‘)
80                     hh.push_back(P(i,j));
81             }
82         }
83         for(int i = 0;i<=2*mm.size()+1;i++)
84             g[i].clear();
85         for(int i = 0;i<mm.size();i++){
86             for(int j = 0;j<hh.size();j++){
87                 addedge(i+1,mm.size()+j+1,1,abs(mm[i].first-hh[j].first)+abs(mm[i].second-hh[j].second));
88             }
89         }
90         int s = 0,t = 2*mm.size()+1;
91         for(int i = 0;i<mm.size();i++)
92             addedge(s,i+1,1,0);
93         for(int i = 0;i<hh.size();i++)
94             addedge(mm.size()+i+1,t,1,0);
95         cout << solve(s,t,mm.size()) << endl;
96     }
97 }
时间: 2024-10-12 02:07:00

POJ2195 最小费用流的相关文章

最小费用流 poj2195

Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17955   Accepted: 9145 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 vertical

[POJ2195]Going Home(带权最大匹配,KM,最小费用流)

题目链接:http://poj.org/problem?id=2195 题意:给个图,m代表人H代表房子.每一个m要有一个H,代价是曼哈顿距离.问让所有m找到房子的最小花费. 可以直接枚举m和H建二分图跑KM. 1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include

poj2195&amp;&amp;hdu1533 最小费用流

这题也可以用km做,我写的代码km比费用流快很多. 最小费用流: #include<stdio.h> #include<string.h> #include<math.h> #include<queue> #include<stdlib.h> #define INF 1000000000 using namespace std; const int maxn = 1100; struct Set { int x,y; }mnum[110*110]

POJ2195 Going Home 【最小费用流】+【二分图最佳匹配】

Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18169   Accepted: 9268 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 vertical

POJ 2195Going Home(网络流之最小费用流)

题目地址:POJ2195 本人职业生涯费用流第一发!!快邀请赛了,决定还是多学点东西,起码碰到简单的网络流要A掉.以后最大流费用流最小割就一块刷. 以前费用流在我心目中一直是高大上,高不可攀的形象,可这两天才发现,原来费用流就是一个spfa再加点东西...一直以为费用流会比最大流的isap要麻烦好多,毕竟多了一个费用的元素....我真的错了..仔细研究了一下,只用一个spfa确实就可以解决了... 这题是一个入门题(虽然还多了些处理..),建图思路很简单,就是将人与源点相连,流量为1,费用为0,

POJ-2195(最小费用最大流+MCMF算法)

Going Home POJ-2195 这题使用的是最小费用流的模板. 建模的时候我的方法出现错误,导致出现WA,根据网上的建图方法没错. 这里的建图方法是每次到相邻点的最大容量为INF,而花费为1,因为花费等于距离.但是需要增加一个源点和一个汇点,然后将每个人和源点相连,每个房子和汇点相连,容量都为1,费用都为0. #include<iostream> #include<algorithm> #include<cstring> #include<queue>

HDU 3488Tour(网络流之最小费用流)

题目地址:hdu3488 这题跟上题基本差不多啊....详情请戳这里. 另外我觉得有要改变下代码风格了..终于知道了为什么大牛们的代码的变量名都命名的那么长..我决定还是把源点与汇点改成source和sink吧..用s和t太容易冲突了...于是如此简单的一道题调试到了现在..sad... 代码如下: #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #

【bzoj1834】[ZJOI2010]network 网络扩容 最大流+最小费用流

题目描述 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不扩容的情况下,1到N的最大流: 2. 将1到N的最大流增加K所需的最小扩容费用. 输入 输入文件的第一行包含三个整数N,M,K,表示有向图的点数.边数以及所需要增加的流量. 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边. 输出 输出文件一行包含两个整数,分别表示问题1和问题2的答案. 样例输入 5 8 2 1 2 5 8 2 5 9

poj2135 最小费用流

添加超级源点(与点1之间的边容量为2,权值为0)和超级汇点(与点N之间的边容量为2,权值为0),求流量为2的最小费用流.注意是双向边. #include <iostream> #include <cstdio> #include <vector> #include <queue> using namespace std; const long long INF = 0x3f3f3f3f3f3f3f3f; typedef long long ll; typed