hdu 1533 Going Home (最小费用最大流)
2015-07-26 21:16
621 查看
/* 题意: 给定一个N*M的地图,地图上有若干个man和house,且man与house的数量一致。 man每移动一格需花费$1(即单位费用=单位距离) ,一间house只能入住一个man。现在要求所有的man都入住house,求最小费用。 把man作为一个顶点集合U,house作为另一个顶点集合V,把U中所有点到V中所有点连线, 费用cost[u][v]为abs(△x)+abs(△y),反向弧费用cost[v][u]= -cost[u][v], 容量cap[u][v]=1,构成一个多源多汇的二分图。 由于每一个多源多汇的网络流都必有一个与之对应的单源单汇的网络流, 为了便于解题,由此构造一个超级源s和超级汇t,超级源s与U中所有点相连, 费用cost[s][u]=0(这是显然的) 容量cap[s][u]=1;V中所有点与超级汇t相连,费用cost[v][t]=0(这是显然的),容量cap[t][v]=1。 */ # include <stdio.h> # include <algorithm> # include <stack> # include <queue> # include <string.h> using namespace std; # define MAXM 500010//边 # define MAXN 10010//点 # define INF 0x3fffff struct node { int x; int y; }; node cotm[5010],coth[5010]; 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(int n) { N = n; 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; } int main() { int n,m,cot1,cot2,i,j; char a[110][110]; while(~scanf("%d%d",&n,&m),n+m) { cot1=0; cot2=0; for(i=0; i<n; i++) scanf("%s",a[i]); for(i=0; i<n; i++) { for(j=0; j<m; j++) { if(a[i][j]=='m') { cot1++; cotm[cot1].x=i+1; cotm[cot1].y=j+1; } else if(a[i][j]=='H') { cot2++; coth[cot2].x=i+1; coth[cot2].y=j+1; } } } // printf("%d %d\n",cot1,cot2); int sa=0;//超级源点 int ed=cot1+cot2+1;//超级汇点 init(ed+1);//总节点数 for(i=1; i<=cot1; i++) addedge(sa,i,1,0); for(i=1; i<=cot2; i++) addedge(i+cot1,ed,1,0); for(i=1; i<=cot1; i++) { for(j=1; j<=cot2; j++) { int x=abs(cotm[i].x-coth[j].x)+abs(cotm[i].y-coth[j].y); addedge(i,j+cot1,1,x); } } int cost; int aa=minCostMaxflow(sa,ed,cost); printf("%d\n",cost); } return 0; }
相关文章推荐
- Google Play 服务提示更新、Google play 闪退等问题
- HDU 2952 Counting Sheep (DFS)
- HDU 5310 Souvenir
- poj2195 Going Home(二分图的最小权匹配)
- hdoj 3715 Go Deeper 【2-sat 判断可行解 + 二分】
- CDOJ 486 Good Morning 傻逼题
- windows环境下搭建go环境+sublime2
- 042.@interface 非正式协议(category)
- 【Go语言】【16】GO语言的并发
- ORA-00932: inconsistent datatypes: expected - got CLOB
- 【LeetCode】Algorithms 题集(三)
- 轻松上Google
- 获取美版的google play store
- HDU 1124 Factorial(数论)
- POJ 1006 Biorhythms(中国剩余定理)
- django序列化时使用外键的真实值
- 040.category 调用私有方法
- 039.category 对类进行模块化设计
- greedy algorithm DEMO
- Codeforces Round #313 (Div. 2) C. Gerald's Hexagon