设一个虚拟source和sink,source连man,费用为0,home连sink,费用为0,与source和sink连接的边的容量为真是所有边容量最大值或不最大值更大。
1·ek(900多ms)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #define inf 0x7ffffff using namespace std; const int N=100+5; struct node { int u,v,w,next; int fee; }e[N*N*2]; struct nodee { int x,y; }p[N*N],h[N*N]; int st,ed; int pnum,hnum; int head[N*N],cnt; void Init() { memset(head,-1,sizeof(head)); cnt=0; } void add(int a,int b,int c,int f) { e[cnt].u=a; e[cnt].v=b; e[cnt].w=c; e[cnt].fee=f; e[cnt].next=head[a]; head[a]=cnt++; e[cnt].u=b; e[cnt].v=a; e[cnt].w=0; e[cnt].fee=-f; e[cnt].next=head[b]; head[b]=cnt++; } void Input(int n,int m) { pnum=0;hnum=0; char map[N][N]; for(int i=0;i<n;i++) scanf("%s",map[i]); for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { if(map[i][j]=='H') { h[hnum].x=i; h[hnum++].y=j; } else if(map[i][j]=='m') { p[pnum].x=i; p[pnum++].y=j; } } } } int abs(int a) { if(a>0) return a; return -a; } void pretreatment() { Init(); st=0; ed=hnum+pnum+1; for(int i=0;i<pnum;i++) { add(st,i+1,1,0); for(int j=0;j<hnum;j++) { int k=abs(p[i].x-h[j].x)+abs(p[i].y-h[j].y); add(i+1,pnum+1+j,1,k); } add(i+1+pnum,ed,1,0); } } class ek { public: inline int spfa() { int vis[N*N]; queue<int>q; while(!q.empty()) q.pop(); for(int i=0;i<=ed;i++) dis[i]=inf; memset(vis,0,sizeof(vis)); memset(pre,-1,sizeof(pre)); dis[st]=0; vis[st]=1; q.push(st); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];i+1;i=e[i].next) { int v=e[i].v; if(dis[v]>dis[u]+e[i].fee&&e[i].w>0) { dis[v]=dis[u]+e[i].fee; pre[v]=u; pe[v]=i; if(!vis[v]) { vis[v]=1; q.push(v); } } } } return pre[ed]!=-1; } inline int Min(int a,int b) { if(a<b) return a; return b; } inline int solve() { int ans=0; while(spfa()) { int min=inf; for(int i=ed;i!=st;i=pre[i]) min=Min(min,e[pe[i]].w); for(int i=ed;i!=st;i=pre[i]) { e[pe[i]].w-=min; e[pe[i]^1].w+=min; } ans+=dis[ed]; //cout<<"min="<<min; //cout<<" ,dis[ed]="<<dis[ed]<<endl; } return ans; } private: int dis[N*N],pre[N*N],pe[N*N]; }seg; void treatment() { printf("%d\n",seg.solve()); } int main() { int n,m; while(~scanf("%d%d",&n,&m),n+m) { Input(n,m); pretreatment(); treatment(); } return 0; }
2·Dinic(1200多ms)不知道为啥这个比ek慢
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #define inf 0x7ffffff using namespace std; const int N=100+5; struct node { int u,v,w,next; int fee; }e[N*N*2]; struct nodee { int x,y; }p[N*N],h[N*N]; int st,ed; int pnum,hnum; int head[N*N],cnt; void Init() { memset(head,-1,sizeof(head)); cnt=0; } void add(int a,int b,int c,int f) { e[cnt].u=a; e[cnt].v=b; e[cnt].w=c; e[cnt].fee=f; e[cnt].next=head[a]; head[a]=cnt++; e[cnt].u=b; e[cnt].v=a; e[cnt].w=0; e[cnt].fee=-f; e[cnt].next=head[b]; head[b]=cnt++; } void Input(int n,int m) { pnum=0;hnum=0; char map[N][N]; for(int i=0;i<n;i++) scanf("%s",map[i]); for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { if(map[i][j]=='H') { h[hnum].x=i; h[hnum++].y=j; } else if(map[i][j]=='m') { p[pnum].x=i; p[pnum++].y=j; } } } } int abs(int a) { if(a>0) return a; return -a; } void pretreatment() { Init(); st=0; ed=hnum+pnum+1; for(int i=0;i<pnum;i++) { add(st,i+1,1,0); for(int j=0;j<hnum;j++) { int k=abs(p[i].x-h[j].x)+abs(p[i].y-h[j].y); add(i+1,pnum+1+j,1,k); } add(i+1+pnum,ed,1,0); } } class ek { public: inline int spfa() { int vis[N*N]; queue<int>q; while(!q.empty()) q.pop(); for(int i=0;i<=ed;i++) { dis[i]=inf; vis[i]=0; } dis[st]=0; vis[st]=1; q.push(st); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];i+1;i=e[i].next) { int v=e[i].v; if(dis[v]>dis[u]+e[i].fee&&e[i].w>0) { dis[v]=dis[u]+e[i].fee; pe[v]=i; if(!vis[v]) { vis[v]=1; q.push(v); } } } } return dis[ed]!=inf; } inline int Min(int a,int b) { if(a<b) return a; return b; } int dfs(int u,int flow) { int cost=0; if(u==ed) { ans+=dis[u]; return flow; } for(int i=head[u];i+1;i=e[i].next) { int v=e[i].v; if(pe[v]==i&&e[i].w>0) { int min=dfs(v,Min(e[i].w,flow-cost)); if(min>0) { e[i].w-=min; e[i^1].w+=min; cost+=min; if(cost==flow) break; } else pe[v]=-1; } } return cost; } inline int solve() { ans=0; int res=0; while(spfa()) { res+=dfs(st,inf); } return ans; } private: int dis[N*N],pre[N*N],pe[N*N],ans; }seg; void treatment() { printf("%d\n",seg.solve()); } int main() { int n,m; while(~scanf("%d%d",&n,&m),n+m) { Input(n,m); pretreatment(); treatment(); } return 0; }