HDU 1533 (最小费用最大流)(spfa+ek或spfa+dinic)

设一个虚拟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;
}

你可能感兴趣的:(网络流,最小费用最大流)