POJ2195:Going Home——题解
http://poj.org/problem?id=2195
题目大意:
有些人和房子,一个人只能进一个房子,人走到房子的路程即为代价。
求所有人走到房子后的最小代价。
——————————————————
bfs处理每个人到每个房的最短路之后就是裸的费用流了,不解释。
#include<cstdio> #include<iostream> #include<queue> #include<cstring> #include<algorithm> #include<cctype> using namespace std; typedef long long ll; const int INF=1e9; const int N=10010; const int M=22000; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct node{ int nxt; int to; int w; int b; }edge[M]; int head[N],cnt=-1; void add(int u,int v,int w,int b){ cnt++; edge[cnt].to=v; edge[cnt].w=w; edge[cnt].b=b; edge[cnt].nxt=head[u]; head[u]=cnt; return; } int dis[N]; bool vis[N]; inline bool spfa(int s,int t,int n){ deque<int>q; memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++)dis[i]=INF; dis[t]=0;q.push_back(t);vis[t]=1; while(!q.empty()){ int u=q.front(); q.pop_front();vis[u]=0; for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; int b=edge[i].b; if(edge[i^1].w&&dis[v]>dis[u]-b){ dis[v]=dis[u]-b; if(!vis[v]){ vis[v]=1; if(!q.empty()&&dis[v]<dis[q.front()]){ q.push_front(v); }else{ q.push_back(v); } } } } } return dis[s]<INF; } int ans=0; int dfs(int u,int flow,int m){ if(u==m){ vis[m]=1; return flow; } int res=0,delta; vis[u]=1; for(int e=head[u];e!=-1;e=edge[e].nxt){ int v=edge[e].to; int b=edge[e].b; if(!vis[v]&&edge[e].w&&dis[u]-b==dis[v]){ delta=dfs(v,min(edge[e].w,flow-res),m); if(delta){ edge[e].w-=delta; edge[e^1].w+=delta; res+=delta; ans+=delta*b; if(res==flow)break; } } } return res; } inline int costflow(int S,int T,int n){ while(spfa(S,T,n)){ do{ memset(vis,0,sizeof(vis)); dfs(S,INF,T); }while(vis[T]); } return ans; } int num1=0,num2=0; int mp[101][101]; int pos[101][101]; int pdis[101][101]; bool walk[101][101]; int dx[4]={0,-1,0,1}; int dy[4]={1,0,-1,0}; void bfs(int xx,int yy,int n,int m){ queue<int>q1,q2,q3,q4; memset(walk,0,sizeof(walk)); memset(pdis,127,sizeof(pdis)); pdis[xx][yy]=0; q1.push(xx);q2.push(yy); walk[xx][yy]=1; while(!q1.empty()){ int x=q1.front(),y=q2.front(); q1.pop(),q2.pop(); if(mp[x][y]>0){ q3.push(x);q4.push(y); } for(int i=0;i<4;i++){ int nx=x+dx[i],ny=y+dy[i]; if(nx<=0||ny<=0||nx>n||ny>m||walk[nx][ny])continue; walk[nx][ny]=1; pdis[nx][ny]=pdis[x][y]+1; q1.push(nx);q2.push(ny); } } while(!q3.empty()){ int nx=q3.front(),ny=q4.front(); q3.pop();q4.pop(); add(pos[xx][yy],mp[nx][ny]+num1,1,pdis[nx][ny]); add(mp[nx][ny]+num1,pos[xx][yy],0,-pdis[nx][ny]); } return; } void restart(){ memset(head,-1,sizeof(head)); memset(mp,0,sizeof(mp)); memset(pos,0,sizeof(pos)); cnt=-1; ans=0; num1=0; num2=0; return; } int main(){ int n,m; while(scanf("%d%d",&n,&m)!=EOF&&n&&m){ restart(); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ char ch; cin>>ch; if(ch=='m'){ num1++; mp[i][j]=-1; pos[i][j]=num1; }else if(ch=='H'){ num2++; mp[i][j]=num2; } } } int S=num1+num2+1,T=S+1; for(int i=1;i<=num1;i++){ add(S,i,1,0); add(i,S,0,0); } for(int i=1;i<=num2;i++){ add(i+num1,T,1,0); add(T,i+num1,0,0); } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(mp[i][j]==-1){ bfs(i,j,n,m); } } } printf("%d\n",costflow(S,T,T)); } return 0; }