近日好不容易在自救之路写完暑训遗留下来的网络流8题,在此回顾一下。
Going Home POJ - 2195
题意:m要去H,一个H只能容纳一个m,一步一块钱,问最小花费。
思路:最小费用最大流的板子题。有博客用了Dijkstra,不过在我看来,存在负权边的图是不能使用Dijkstra的,所以虽然我曾立誓再也不写SPFA,现在也不得不屈服了。
1 #include<iostream> 2 #include<algorithm> 3 #include<vector> 4 #include<stack> 5 #include<queue> 6 #include<map> 7 #include<set> 8 #include<cstdio> 9 #include<cstring> 10 #include<cmath> 11 #include<ctime> 12 #define fuck(x) cout<<#x<<" = "<<x<<endl; 13 #define ls (t<<1) 14 #define rs ((t<<1)+1) 15 using namespace std; 16 typedef long long ll; 17 typedef unsigned long long ull; 18 const int maxn = 1024; 19 const int inf = 2.1e9; 20 const ll Inf = 999999999999999999; 21 const int mod = 1000000007; 22 const double eps = 1e-6; 23 const double pi = acos(-1); 24 int n,m; 25 char mp[108][108]; 26 struct node 27 { 28 int x,y; 29 }p1[maxn],p2[maxn]; 30 int Head[maxn],Next[maxn*maxn],v[maxn*maxn],w[maxn*maxn],cap[maxn*maxn],cnt; 31 int t1,t2;int ans; 32 void init() 33 { 34 t1=1;cnt=t2=ans=0; 35 memset(Head,-1,sizeof(Head)); 36 } 37 38 void add(int x,int y,int z,int f){ 39 // cout<<x<<" "<<y<<" "<<z<<endl; 40 v[cnt]=y; 41 w[cnt]=z; 42 cap[cnt]=f; 43 Next[cnt]=Head[x]; 44 Head[x]=cnt++; 45 46 v[cnt]=x; 47 w[cnt]=-z; 48 cap[cnt]=0; 49 Next[cnt]=Head[y]; 50 Head[y]=cnt++; 51 } 52 bool vis[maxn]; 53 int dis[maxn]; 54 int prevv[maxn],preve[maxn]; 55 int s,t; 56 bool spfa() 57 { 58 queue<int>q; 59 memset(vis,0,sizeof(vis)); 60 for(int i=1;i<=t;i++){ 61 dis[i]=inf; 62 } 63 64 dis[s]=0; 65 q.push(s); 66 while(!q.empty()){ 67 int u=q.front(); 68 q.pop(); 69 vis[u]=false; 70 for(int k=Head[u];k!=-1;k=Next[k]){ 71 if(cap[k]&&dis[v[k]]>dis[u]+w[k]){ 72 dis[v[k]]=dis[u]+w[k]; 73 prevv[v[k]]=u; 74 preve[v[k]]=k; 75 76 if(!vis[v[k]]){ 77 vis[v[k]]=true; 78 q.push(v[k]); 79 } 80 } 81 } 82 } 83 if(dis[t]==inf){return false;} 84 else return true; 85 } 86 int min_cost_flow() 87 { 88 while(spfa()){ 89 for(int i=t;i!=s;i=prevv[i]){ 90 int k=preve[i]; 91 cap[k]-=1; 92 cap[k^1]+=1; 93 } 94 ans+=dis[t]; 95 } 96 97 } 98 99 int main() 100 { 101 // ios::sync_with_stdio(false); 102 // freopen("in.txt","r",stdin); 103 104 while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){ 105 init(); 106 for(int i=1;i<=n;i++){ 107 scanf("%s",mp[i]+1); 108 for(int j=1;j<=m;j++){ 109 if(mp[i][j]=='m'){p1[++t1]=node{i,j};} 110 else if(mp[i][j]=='H'){p2[++t2]=node{i,j};} 111 } 112 } 113 s=1;t=t1+t2+1; 114 for(int i=2;i<=t1;i++){ 115 add(s,i,0,1); 116 for(int j=1;j<=t2;j++){ 117 add(i,j+t1,abs(p1[i].x-p2[j].x)+abs(p1[i].y-p2[j].y),inf); 118 } 119 } 120 for(int i=1;i<=t2;i++){ 121 add(i+t1,t,0,1); 122 } 123 124 min_cost_flow(); 125 printf("%d\n",ans); 126 } 127 128 return 0; 129 }