poj 2195 Going Home(KM||费用流)
来源:互联网 发布:mac 文件共享 灰色 编辑:程序博客网 时间:2024/06/05 19:48
http://poj.org/problem?id=2195
题目大意:
给定一个N*M的地图,地图上有一定数量的m(代表人)和H(代表房子),两者数量相等;
要求求出把所有m移动到H的位置上总距离最小为多少;
思路:
用最优二分匹配或者最小费用最大流都能做,觉得用最优二分匹配会简单一些;
建图把m和H分别作为二分图的两个顶点集合vx和vy,求出两两之间的距离,用km算法求出最优匹配;
要注意的是,要求距离的最短,而km求的是最大匹配值,所以建图的时候距离要取反;
这是KM做的,费用流做的在下面;
#include<iostream>#include<cmath>using namespace std;const int MAX=105;const int inf=1<<30;int n,lack;int map[MAX][MAX]; char maps[MAX][MAX];int dx[MAX],dy[MAX]; int link[MAX];bool visx[MAX],visy[MAX]; bool DFS(int v){ visx[v]=true; for(int i=0;i<n;i++) { if(visy[i]) continue; int t=dx[v]+dy[i]-map[v][i]; if(!t) { visy[i]=true; if(link[i]==-1||DFS(link[i])) { link[i]=v; return true; } } else if(t<lack) lack=t; } return false;}void KM(){ int i,j; memset(dx,0,sizeof(dx)); memset(dy,0,sizeof(dy)); memset(link,-1,sizeof(link)); for(i=0;i<n;i++) { for(j=0;j<n;j++) if(map[i][j]>dx[i]) dx[i]=map[i][j]; } for(i=0;i<n;i++) { while(true) { memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); lack=0x7fffffff; if(DFS(i)) break; for(j=0;j<n;j++) { if(visx[j]) dx[j]-=lack; if(visy[j]) dy[j]+=lack; } } }}int main(int i,int j,int k,int l){ int row,col,ans,numi,numj; while(scanf("%d%d",&row,&col)&&(row+col)) {/*Initial*/ n=ans=numi=numj=0; memset(link,-1,sizeof(link)); memset(map,0,sizeof(map));/*Input*/ for(i=0;i<row;i++) { scanf("%*c"); for(j=0;j<col;j++) { scanf("%c",&maps[i][j]); if(maps[i][j]=='m') n++; } }/*Structure Graph*//*±ßȨֵ±äΪ¸ºÈ¨£¬Çó³ö×î´óÆ¥ÅäÖµ¼´Îª×îС¾àÀë×ܺÍ*/ for(i=0;i<row;i++) { for(j=0;j<col;j++) { if(maps[i][j]=='m') { for(k=0;k<row;k++) { for(l=0;l<col;l++) { if(maps[k][l]=='H') map[numi][numj++]=-(abs(k-i)+abs(l-j)); //±ßΪ¸ºÈ¨Öµ } } numi++; numj=0; } } } KM(); int ans=0; for(i=0;i<n;i++) { if(link[i]!=-1) ans+=map[link[i]][i]; } printf("%d\n",-ans); } return 0;}
-------------------------------------------------华丽的分割线------------------------------------------
#include<iostream>#include<queue>#include<cmath>#include<cstring>using namespace std;const int inf=1<<30;const int N=100500;const int M=200500;class Edge{public:int u;int v;int cost;int flow;int next;}edge[M<<3];class Node{public:int x;int y;}man[105],house[105];int s,t;int edge_num;int max_flow;int head[N];int pre[N];int dist[N];bool vis[N];char map[105][105];void addedge(int u,int v,int cost,int flow){edge[edge_num].u=u;edge[edge_num].v=v;edge[edge_num].flow=flow;edge[edge_num].cost=cost;edge[edge_num].next=head[u];head[u]=edge_num++;edge[edge_num].u=v;edge[edge_num].v=u;edge[edge_num].flow=0;edge[edge_num].cost=-cost;edge[edge_num].next=head[v];head[v]=edge_num++;return ;}/*SPFA 对费用求最短路*/bool spfa(){queue <int> que;memset(pre,-1,sizeof(pre));memset(vis,false,sizeof(vis));for(int j=0;j<=t;j++)dist[j]=inf;dist[s]=0;vis[s]=true;que.push(s);while(!que.empty()){int x=que.front();que.pop();int y;for(int i=head[x];~i;i=edge[i].next){y=edge[i].v;if(edge[i].flow && dist[y]>dist[x]+edge[i].cost){dist[y]=dist[x]+edge[i].cost;pre[y]=i;if(!vis[y]){vis[y]=true;que.push(y);}}}vis[x]=false;}if(dist[t]==inf)return false;return true;}void argument_flow(){int v,alfa=inf; for(v=pre[t];~v;v=pre[ edge[v].u ]){if(alfa>edge[v].flow)alfa=edge[v].flow;}for(v=pre[t];~v;v=pre[ edge[v].u ]){edge[v].flow -= alfa;edge[v^1].flow += alfa;}max_flow += alfa*dist[t];}int main(int i,int j){int n,m;while(~scanf("%d %d",&n,&m)&&n&&m){edge_num=0;max_flow=0;s=0;t=n*m+1;memset(head,-1,sizeof(head));int p=0;int q=0;/*Input & Structure Graph*/for(i=1;i<=n;i++){scanf("%s",map[i]+1);for(j=1;j<=m;j++){int x=(i-1)*m+j;if(map[i][j]=='m'){addedge(s,x,0,1);man[++p].x=i;//储存人的坐标man[p].y=j;}if(map[i][j]=='H'){addedge(x,t,0,1);house[++q].x=i;//储存房子的坐标house[q].y=j;}}}for(i=1;i<=p;i++){/*人和房子之间连边*/for(j=1;j<=q;j++)addedge(man[i].x*m+man[i].y-m,house[j].x*m+house[j].y-m,abs(man[i].x-house[j].x)+abs(man[i].y-house[j].y),1);}while(spfa())argument_flow();printf("%d\n",max_flow);}return 0;}
- poj 2195 Going Home (费用流/KM)
- poj 2195 Going Home(KM||费用流)
- POJ 2195Going Home(KM或费用流)
- poj2195 Going Home(费用流|KM)
- POJ 2195 Going Home 费用流模版题(附KM算法,转)
- POJ 2195-Going Home(KM算法/最小费用最大流算法)
- POJ 2195 Going Home(KM)
- POJ 2195 Going Home 最小费用最大流 or KM算法
- POJ-2195 Going Home (最小费用最大流初学 && 最大权二分匹配—KM算法)
- POJ 2195 Going Home(费用流)
- poj 2195 Going Home (费用流)
- [费用流] POJ 2195 Going Home
- poj 2195 Going Home【zkw费用流】
- POJ 2195 Going Home(费用流)
- [POJ 2195]Going Home[费用流]
- Poj 2195 Going Home【费用流Min_Cost_Max_flow】
- POJ 2195 Going Home <最小费用流>
- Poj 2195 Going Home(费用流)
- PythonChallenge 挑战之路 Level-7
- 产品经理(PM)常用原型图设计工具 Axure RP 等等
- postgresl问题探讨1
- 前端开发学习之道:jQuery 1.7.1API手册
- hdu4341(分组背包)
- poj 2195 Going Home(KM||费用流)
- 3.4. 事务
- Apache Avro 与 Thrift 比较
- PostGreSQL“快照”
- 搜索引擎网页排序算法
- Spice代码阅读一:Spice Client 与 Spice Server 通道建立过程
- 多步OLE DB操作产生错误……
- extjs多级树形列表——json传参
- python解数独--世界最难数独2.3秒完成