【POJ3422】Kaka's Matrix Travels

时间:2021-08-03
本文章向大家介绍【POJ3422】Kaka's Matrix Travels,主要包括【POJ3422】Kaka's Matrix Travels使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目

解析:

由于一个点可以走多次,而且第二次走没有分数,考虑拆点。每个点到它拆出来的点连两条边,一条的容量设成1,费用设为该格子分数的相反数。表示,这条边只能走一次,且走这条边能拿到分数;第二条的容量设成无穷大,费用设成\(0\),表示,这个格子可以重复走,但是没有分数。然后在拆出来的点和它能到的点连边,容量无穷大,费用为\(0\)就可以了。最后费用流增广\(k\)次,得到的最小费用的相反数即为最大值。

code:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
using namespace std;

const int Maxn=5005;
const int Maxm=100005;
const int inf=1e9;
int n,m,size=-1,s,t,k,sum;
int dis[Maxn],first[Maxn],v[Maxn],tmp[Maxn];
struct shu{int to,next,l,c;}e[Maxm<<1];

inline int get_int()
{
	int x=0,f=1;char c;
	while(!isdigit(c) && c!='-') c=getchar();
	if(c=='-') f=-1,c=getchar();
	while(isdigit(c)) x=(x<<3)+(x<<1)+c-'0',c=getchar();
	return x*f;
}

inline int min(int x,int y){return x>y ? y : x;}

inline void add(int x,int y,int l,int c)
{
	e[++size].next=first[x],first[x]=size,e[size].to=y,e[size].l=l,e[size].c=c;
	e[++size].next=first[y],first[y]=size,e[size].to=x,e[size].l=0,e[size].c=-c;
}

inline void init()
{
	n=get_int(),k=get_int(),t=n*n*2+1;
	int len=n*n,x,pos;
	for(int i=s;i<=t;i++) first[i]=-1;
	for(int i=0;i<n;i++)
	  for(int j=1;j<=n;j++)
	  {
	  	x=get_int(),pos=i*n+j;
	  	add(pos,len+pos,1,-x),add(pos,len+pos,len,0);
	  	if(i<n-1) add(len+pos,pos+n,len,0);
	  	if(j<n) add(len+pos,pos+1,len,0);
	  }
	add(s,1,inf,0),add(t-1,t,inf,0);
}

inline bool spfa()
{
	queue<int>q;
	for(int i=s;i<=t;i++) dis[i]=inf,tmp[i]=first[i];
	q.push(s),v[s]=1,dis[s]=0;
	while(!q.empty())
	{
	  int p=q.front();q.pop(),v[p]=0;
	  for(register int u=first[p];~u;u=e[u].next)
	  {
	  	int to=e[u].to;
	  	if(!e[u].l || dis[to]<=dis[p]+e[u].c) continue;
	  	dis[to]=dis[p]+e[u].c;
	  	if(!v[to]) v[to]=1,q.push(to);
	  }
	}
	return dis[t]!=inf;
}

inline int dfs(int p,int flow)
{
	if(p==t) return flow;
	int s=0;v[p]=1;
	for(register int &u=tmp[p];~u;u=e[u].next)
	{
	  int to=e[u].to;
	  if(!e[u].l || dis[to]!=dis[p]+e[u].c || v[to]) continue;
	  int minn=dfs(to,min(flow-s,e[u].l));
	  e[u].l-=minn,e[u^1].l+=minn,s+=minn,sum+=minn*e[u].c;
	  if(s==flow) break;
	}
	v[p]=0;
	return s;
}

inline void solve()
{
	while(spfa())
	  while(dfs(s,inf)&&k)
	  {
	  	k--;
	  	if(!k) return; 
	  }
}

int main()
{
	freopen("lx.in","r",stdin);

	init();
	if(k) solve();
	cout<<-sum;
	return 0;
}

原文地址:https://www.cnblogs.com/Tarjan-Zeng/p/15094253.html