poj 3422 (费用流)

从左上角到有下角k次能获得的最大值。

跟hdu 2686一样的题目,这题一个点可以重复走,只能得到一次值。

poj 3422 (费用流)




 

#include<stdio.h>

#include<string.h>

#include<queue>

const int N=5100;

const int inf=0x3fffffff;

using namespace std;

int dist[N],head[N],num,start,end,n,vis[N],pre[N];

struct edge

{

	int st,ed,cost,flow,next;

}e[N*10];

void addedge(int x,int y,int c,int w)

{

	e[num].st=x;e[num].ed=y;e[num].cost=c; e[num].flow=w;e[num].next=head[x];head[x]=num++;

	e[num].st=y;e[num].ed=x;e[num].cost=-c;e[num].flow=0;e[num].next=head[y];head[y]=num++;

}

int SPFA()

{

	queue<int>Q;

	int i,v,u;

	for(i=0;i<=end;i++)

	{dist[i]=-1;vis[i]=0;pre[i]=-1;}

	dist[start]=0;vis[start]=1;

	Q.push(start);

	while(!Q.empty())

	{

		u=Q.front();Q.pop();

		vis[u]=0;

		for(i=head[u];i!=-1;i=e[i].next)

		{

			v=e[i].ed;

			if(e[i].flow>0&&dist[v]<dist[u]+e[i].cost)

			{

				dist[v]=dist[u]+e[i].cost;

				pre[v]=i;

				if(vis[v]==0)

				{

					Q.push(v);

					vis[v]=1;

				}

			}

		}

	}

	if(pre[end]==-1)

		return 0;

	return 1;

}

int Maxcost()

{

	int i,maxflow=0,minflow,maxcost=0;

	while(SPFA())

	{

		minflow=inf;

		for(i=pre[end];i!=-1;i=pre[e[i].st])

		 if(minflow>e[i].flow)

			 minflow=e[i].flow;

		 maxflow+=minflow;

		 for(i=pre[end];i!=-1;i=pre[e[i].st])

		 {

			 e[i].flow-=minflow;

			 e[i^1].flow+=minflow;

			 maxcost+=e[i].cost;

		 }

	}

	//printf("maxflow=%d\n",maxflow);

	return maxcost;

}

int main()

{

	int i,j,t,x,w,k;

	while(scanf("%d%d",&n,&k)!=-1)

	{

		t=n*n;start=0;end=t*2+1;num=0;

		memset(head,-1,sizeof(head));

		addedge(start,1,0,k);

		addedge(t+t,end,0,k);

		for(i=1;i<=n;i++)

			for(j=1;j<=n;j++)

			{

				scanf("%d",&w);

				x=i*n+j-n;

				addedge(x,x+t,w,1);

				addedge(x,x+t,0,k-1);

				if(j+1<=n)

					addedge(x+t,x+1,0,k);

				if(i+1<=n)

					addedge(x+t,x+n,0,k);

			}

			printf("%d\n",Maxcost());

	}

	return 0;

}


 


 

你可能感兴趣的:(poj)