最小费用最大流;HDU1533
2015-08-03 10:45
561 查看
//第一次写费用流,有些地方还是不太懂,但是思路很简单。 //建立伴随网络后,每次用spfa找最短路然后增广就好了 #include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <cmath> #define maxN 300 #define maxM 10005 #define INF 0xffffff using namespace std; struct node { int c;//容量 int f;//流量 int c_f;//残留容量 int val;//价值 }G[maxN][maxN]; int n,m; int pre[maxM];//记录前驱点 int dist[maxM];//spfa记录距离 char coord[maxN][maxN];//坐标集 int inq[maxM]; int min_f; int sum; int vertex; struct House { int x; int y; }house[maxN]; struct Man { int x; int y; }man[maxN]; void init() { sum=0; int mcase,hcase; mcase=hcase=0; int i,j; for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { cin>>coord[i][j]; if(coord[i][j]=='m'){ mcase++; man[mcase].x=i; man[mcase].y=j; } if(coord[i][j]=='H'){ hcase++; house[hcase].x=i; house[hcase].y=j; } } } vertex=hcase+mcase+1; for(int u=0;u<=vertex;u++) { for(int v=0;v<=vertex;v++) { G[u][v].c=G[v][u].c=0; G[u][v].f=G[v][u].f=0; G[u][v].c_f=G[v][u].c_f=0; G[u][v].val=G[v][u].val=INF; } } for(i=1;i<=mcase;i++) { G[0][i].val=0; G[0][i].c_f=G[0][i].c=1; for(j=1;j<=hcase;j++) { int len=abs((house[j].x-man[i].x))+abs(house[j].y-man[i].y); G[i][mcase+j].val=len; G[i][mcase+j].c=1; G[i][mcase+j].c_f=1; G[mcase+j][vertex].c=1; G[mcase+j][vertex].c_f=1; G[mcase+j][vertex].val=0; } } } void spfa(int s) { queue<int> q; int i; for(i=0;i<maxN;i++) { dist[i]=INF; pre[i]=-1; inq[i]=0; } dist[s]=0; inq[i]=1; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); inq[u]=0; for(i=0;i<=vertex;i++) { if(G[u][i].c_f==0) continue; if(G[u][i].val==INF) G[u][i].val=-G[i][u].val; //不太懂 if(dist[i]>dist[u]+G[u][i].val) { dist[i]=dist[u]+G[u][i].val; pre[i]=u; if(!inq[i]) { q.push(i); inq[i]=1; } } } } } void argument(int s,int t) { spfa(s); int v; while(pre[t]!=-1) { int u=pre[t]; v=t; sum+=dist[v]; min_f=INF; while(u!=-1) { if(G[u][v].c_f<min_f) min_f=G[u][v].c_f; v=u; u=pre[v]; } u=pre[t];v=t; while(u!=-1) { G[u][v].f+=min_f; G[v][u].f=-G[u][v].f; G[u][v].c_f=G[u][v].c-G[u][v].f; G[v][u].c_f=G[v][u].c-G[v][u].f; v=u; u=pre[v]; } spfa(s); } } int main() { while(cin>>n>>m) { if(n==0&&m==0) break; init(); argument(0,vertex); cout<<sum<<endl; } return 0; }
相关文章推荐
- Poj2638 网络流+最短路+二分答案
- BZOJ3275 Number (最小割)
- [笔记] 网络流-最大流 POJ-1273\HDU-4240
- 上下界网络流初探
- Edmonds-Karp 最大流 hdu 1532 Drained Ditches
- 网络流_poj1273
- POJ 1273 Drainage Ditches 最大流 dinic
- POJ1273-Drainage Ditches
- 【网络流】复杂的大门
- ACM/ICPC World Finals 2013 C Surely You Congest
- 网络流算法整理
- [BZOJ1797][AHOI2009][最大流][强连通分量]Mincut最小割
- [BZOJ2324][ZJOI2011][最小费用最大流]营救皮卡丘
- [BZOJ1834][ZJOI2010][最大流][最小费用最大流]网络扩容
- Topcoder SRM642 TaroCutting
- POJ2391解题报告
- uva 11248
- [网络流24题 #2]太空飞行计划问题
- [网络流24题 #18]分配问题
- [网络流24题 #2]太空飞行计划问题