POJ 2195 Going Home 最小费用流 裸题

给出一个n*m的图,其中m是人,H是房子,.是空地,满足人的个数等于房子数。

现在让每个人都选择一个房子住,每个人只能住一间,每一间只能住一个人。

每个人可以向4个方向移动,每移动一步需要1$,问所有人移动到房子里的最少花费。

其中,n,m<=100,最多有100个人。

最小给用流裸题。

建立一个超级源点,跟每一个房子连一条边,容量为1,花费为0

每一个人与超级汇点连一条边,容量为1,花费为0

一个房子与每一个人建一条边,房子指向人,容量为1,花费用2者的距离(不是直线距离)

然后跑最小费用流算法就可以了。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<vector>
  4 #include<queue>
  5
  6 using namespace std;
  7
  8 const int maxn=205;
  9 const int inf=0x3f3f3f3f;
 10 const int s=0;
 11 int t;
 12 int tot;
 13 char maze[maxn];
 14 char str[maxn][maxn];
 15 bool vis[maxn];
 16 int dis[maxn];
 17 int prev[maxn];
 18 int pree[maxn];
 19
 20 struct Point
 21 {
 22     int x,y;
 23 };
 24 Point point[maxn];
 25 struct Edge
 26 {
 27     int to,cap,cost,rev;
 28 };
 29 vector<Edge>edge[maxn];
 30
 31 inline int get_abs(int tmp)
 32 {
 33     if(tmp>0)
 34         return tmp;
 35     return -tmp;
 36 }
 37
 38 inline int min(int x,int y)
 39 {
 40     return x<y?x:y;
 41 }
 42
 43 inline int get_dis(int i,int j)
 44 {
 45     return get_abs(point[i].x-point[j].x)+get_abs(point[i].y-point[j].y);
 46 }
 47
 48 void addedge(int from,int to,int cap,int cost)
 49 {
 50     edge[from].push_back((Edge){to,cap,cost,edge[to].size()});
 51     edge[to].push_back((Edge){from,0,-cost,edge[from].size()-1});
 52 }
 53
 54 void build_graph(int n,int m)
 55 {
 56     //要从0开始
 57     for(int i=0;i<maxn;i++)
 58         edge[i].clear();
 59     tot=1;
 60     for(int i=1;i<=n;i++)
 61     {
 62         for(int j=1;j<=m;j++)
 63         {
 64             if(str[i][j]==‘H‘)
 65             {
 66                 point[tot].x=i;
 67                 point[tot++].y=j;
 68             }
 69         }
 70     }
 71     for(int i=1;i<=n;i++)
 72     {
 73         for(int j=1;j<=m;j++)
 74         {
 75             if(str[i][j]==‘m‘)
 76             {
 77                 point[tot].x=i;
 78                 point[tot++].y=j;
 79             }
 80         }
 81     }
 82     t=tot;
 83     tot--;
 84     tot/=2;
 85     for(int i=1;i<=tot;i++)
 86     {
 87         addedge(s,i,1,0);
 88         addedge(i+tot,t,1,0);
 89     }
 90     for(int i=1;i<=tot;i++)
 91     {
 92         for(int j=tot+1;j<=tot*2;j++)
 93         {
 94             addedge(i,j,1,get_dis(i,j));
 95         }
 96     }
 97 }
 98
 99 void spfa()
100 {
101     memset(vis,false,sizeof vis);
102     for(int i=0;i<=t;i++)
103         dis[i]=inf;
104     queue<int>que;
105     while(!que.empty())
106         que.pop();
107     que.push(s);
108     dis[s]=0;
109     vis[s]=true;
110     while(!que.empty())
111     {
112         int u=que.front();
113         que.pop();
114         vis[u]=false;   //要记得这步
115         for(int i=0;i<edge[u].size();i++)
116         {
117             Edge &e=edge[u][i];
118             if(e.cap>0&&dis[e.to]>dis[u]+e.cost)
119             {
120                 dis[e.to]=dis[u]+e.cost;
121                 prev[e.to]=u;
122                 pree[e.to]=i;
123                 if(!vis[e.to])
124                 {
125                     vis[e.to]=true;
126                     que.push(e.to);
127                 }
128             }
129         }
130     }
131     return ;
132 }
133
134 int solve()
135 {
136     int ret=0;
137     int flow=tot;
138     while(flow>0)
139     {
140         spfa();
141         int f=flow;
142         for(int i=t;i!=s;i=prev[i])
143         {
144             f=min(f,edge[prev[i]][pree[i]].cap);
145         }
146         flow-=f;
147         ret+=dis[t]*f;
148         for(int i=t;i!=s;i=prev[i])
149         {
150             Edge &e=edge[prev[i]][pree[i]];
151             e.cap-=f;
152             edge[e.to][e.rev].cap+=f;
153         }
154     }
155     return ret;
156 }
157
158 int main()
159 {
160     int n,m;
161     while(~scanf("%d%d",&n,&m))
162     {
163         if(!n&&!m)
164             break;
165         for(int i=1;i<=n;i++)
166         {
167             scanf("%s",str[i]+1);
168         }
169         build_graph(n,m);
170         printf("%d\n",solve());
171     }
172     return 0;
173 }

时间: 2024-08-07 10:23:38

POJ 2195 Going Home 最小费用流 裸题的相关文章

Poj 1469 COURSES -二分图最大匹配裸题

题目:问course是否有完美匹配 /************************************************ Author :DarkTong Created Time :2016/7/30 22:28:35 File Name :Poj_1469.cpp *************************************************/ #include <cstdio> #include <cstring> #include <

zoj 3933 Team Formation(最小费用流裸题)

1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 5 #include<string> 6 #include<algorithm> 7 #include<set> 8 #include<map> 9 #include<vector> 10 #include<stack> 11 #include<queue> 12 #

POJ 3624 Charm Bracelet(01背包裸题)

Charm Bracelet Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 38909   Accepted: 16862 Description Bessie has gone to the mall's jewelry store and spies a charm bracelet. Of course, she'd like to fill it with the best charms possible fro

POJ 2195 Going Home【最小费用流 二分图最优匹配】

题目大意:一个n*m的地图,上面有一些人man(m)和数量相等的house(H) 图上的距离为曼哈顿距离 问所有人住进一所房子(当然一个人住一间咯)距离之和最短是多少? 思路:一个人一间房,明显是二分图的模型,边权为人和房子的曼哈顿距离,然后算一下最小距离即可 懒得学KM了 最小费用流的经典建图 #include #include #include #include #include #define maxn 40000 #define inf 0x3f3f3f3f using namespac

POJ 3164 Command Network 最小树形图-朱刘算法裸题

题目来源:POJ 3164 Command Network 题意:求以1为根的最小树形图 没有输出字符串 思路:直接高朱刘算法 不懂的可以百度 学会了就是直接套模板的事情 其实就是不断消圈而已 不构成圈就有解 无法从根到达其他点就无解 #include <cstdio> #include <cstring> #include <cmath> const int maxn = 110; const int maxm = 50010; const double INF =

POJ 2451 nlog(n)半平面交裸题。

前言       最近学习C#,不过好在当初考计算机二级学习过C++,刚上手没有对C#感到很恐惧.C#视频也看了几天 了,总感觉不总结一下心里没底,现在跟着我从头走进C#之旅吧.     C#是以后总面向对象的编程语言(OOP),C#是从C和C++派生出来的,主要用于开发可以运行在.NET平台 上的应用程序.随着.NET的发展,C#语言简单.现代.面向对象和类型安全显示了一定的优势.     下面我就介绍一些初学者不太理解的一些东西.   C#有以下突出的特点       (1)语法简洁.不允许

POJ 2234 Matches Game(Nim博弈裸题)

Description Here is a simple game. In this game, there are several piles of matches and two players. The two player play in turn. In each turn, one can choose a pile and take away arbitrary number of matches from the pile (Of course the number of mat

POJ 1087 最大流裸题 + map

A Plug for UNIX Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 15597   Accepted: 5308 Description You are in charge of setting up the press room for the inaugural meeting of the United Nations Internet eXecutive (UNIX), which has an int

POJ 3468 线段树裸题

这些天一直在看线段树,因为临近期末,所以看得断断续续,弄得有些知识点没能理解得很透切,但我也知道不能钻牛角尖,所以配合着刷题来加深理解. 然后,这是线段树裸题,而且是最简单的区间增加与查询,我参考了ACdreamer的模板,在此基础上自己用宏定义来精简了一下代码: 1 #include<cstdio> 2 typedef long long LL; 3 #define root int rt, int l, int r 4 #define lson rt*2, l, mid 5 #define