poj3422 最小费用最大流

记得以前做过这样类似的题,因为那时候求的是来回的最大值,直接使用的dp,而且对费用流并不是很清楚,然后又看到了这道题。。。

对点进行拆分建图,一个点拆为两个点a和b,在a和b之间建一条花费为输入值容量为1的边,然后再建一条花费为0容量为k-1的边,对b点对于其右边和下边都建立一条容量为k花费为0的边,加入超级源点和汇点,花费为0容量为k,由此套模板就可以了!

下面是代码:

/
// File Name: 2195.cpp
// Author: wang
// mail: 1062239606@qq.com
// Created Time: 2013/10/25 19:28:26
/
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <cstring>
#include <cmath>

#include <algorithm>
#include<iostream>
#include<queue>
#include <map>
using namespace std;
typedef long long ll;
#define INF (INT_MAX/10)
#define SQR(x) ((x)*(x))
#define rep(i, n) for (int i=0; i<(n); ++i)
#define repf(i, a, b) for (int i=(a); i<=(b); ++i)
#define repd(i, a, b) for (int i=(a); i>=(b); --i)
#define clr(ar,val) memset(ar, val, sizeof(ar))
#define inf 100000000
#define N 5010
class match{
public:
	//s和t要赋值的,并且花费一个为正一个为负刚好抵消的
	int s,t;//源点和结束点的,开始为1 的
	struct node{
		int y,cost,cap,pre;
	};
	node a[N*1000];
	int dis[N];
	bool vis[N];
	int point[N];
	int len,pre[N];
	void init()
	{
		len=0;
		memset(pre,-1,sizeof(pre));
	}
	void addpage(int x,int y,int cap,int cost)
	{
         a[len].y=y;
		 a[len].pre=pre[x];
		 a[len].cap=cap;
		 a[len].cost=cost;
		 pre[x]=len++;
	}
	bool spfa()
	{
        repf(i,1,t) vis[i]=false,dis[i]=inf;
		vis[s]=true; dis[s]=0;
		queue<int>q;
		q.push(s);
		while(!q.empty())
		{
			int x=q.front(); q.pop();
			vis[x]=false;
			for(int i=pre[x]; i!=-1; i=a[i].pre)
			{
				int y=a[i].y;
				if(a[i].cap && dis[y]>dis[x]+a[i].cost)
				{
                    point[y]=i;//记录边的
					dis[y]=dis[x]+a[i].cost;
					if(vis[y]==false)
					{
						vis[y]=true;
						q.push(y);
					}
				}
			}
		}
		if(dis[t]!=inf) return true;
		else return false;
	}
	int fond()
	{
		int ans=0;
		while(spfa())
		{
			int Min=INT_MAX;
            for(int i=t; i!=s; i=a[point[i]^1].y)//最小的容量,进行扩展的
				Min=min(Min,a[point[i]].cap);
			for(int i=t; i!=s; i=a[point[i]^1].y)
			{
				a[point[i]].cap-=Min;
				a[point[i]^1].cap+=Min;
				ans+=Min*a[point[i]].cost;
			}
		}
		return -ans;
	}
};
match sa;
int a[55][55];
int n,m;
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF)
	{
        repf(i,1,n)
			repf(j,1,n)
			scanf("%d",&a[i][j]);
		sa.init();
		sa.s=0; sa.t=2*n*n+1;
		repf(i,1,n)
			repf(j,1,n)
			{
				int k=(i-1)*n+j;//2*k,2*k-1
                sa.addpage(2*k-1,2*k,1,-a[i][j]);
				sa.addpage(2*k,2*k-1,0,a[i][j]);
				sa.addpage(2*k-1,2*k,m-1,0);
				sa.addpage(2*k,2*k-1,0,0);
				if(i<n)
					sa.addpage(2*k,2*(i*n+j)-1,m,0),
						sa.addpage(2*(i*n+j)-1,2*k,0,0);
				if(j<n)
					sa.addpage(2*k,2*(i*n-n+j+1)-1,m,0),
						sa.addpage(2*(i*n-n+j+1)-1,2*k,0,0);
			}
	   sa.addpage(sa.s,1,m,0);
	   sa.addpage(1,sa.s,0,0);
	   sa.addpage(2*n*n,2*n*n+1,m,0);
	   sa.addpage(2*n*n+1,2*n*n,0,0);
	   printf("%d\n",sa.fond());
	}
	return 0;
}


百度百科创建词条工具V2.7 我们先了解一下百度百科的优势: 1.权威性,广大网民对百度百科信任度特别高,容易受百科中相关信息影响 2.排名好,绝大部分百科词条(即关键词)能排至各大搜索引擎的前三位 3.流量大,一般词条每天浏览量不亚于一个中型企业站每天的总流量 4.转化率高,百科成为网民上网查资料必看的网站,转化为客户的几率较PPC及PM广告大得多。如病人及其家属查找某疾病如何治疗时,必看百科 5.长期有效,百科广告加上之后长期稳定有效,且不产生后续费用 ………   那么,百度百科创建词条工具可以提供哪些帮助呢? 1.创建百科词条,如品牌名、网站名、产品词、人名、公司名… 2.修改百科词条,在原有词条中加入您的内容,如广告内容、名片… 3.删除百科词条,删除不利词条内容或整个词条(不推荐使用) 4.百科内容撰写,根据客户要求编写词条内容 如有其他需求可及时与客服人员沟通,QQ:120962274 百度百科创建词条网站:www.uducn.com   百度百科创建词条常见错误: 1.修改词条原因不明确。例如:修改原因为“编辑词条”“不具体”“更完善”“更具体”等。 2.修改词条原因错误。例如:修改内容是添加图片,填写的修改原因为添加链接。 3.修改词条原因未能明确说明修改的具体区域。例如:修改了词条中的内容并添加了链接,修改原因应写明:添加内容以及链接,必须指出修改或删除的错误内容,并给出具体理由;只修改错别字,必须指明具体的错字;若您修改了表格中的内容,必须明确指出您修改了表格中的哪部分内容。 4.修改词条不可完全删除原词条的内容,可以选择性删除修改原词条内容。 5.编辑者误将角标误添加在段首,或误添加在了完整段落句号之前。   百度百科创建词条时请注意您的词条中不要有违背“百科原则”的内容,否则词条将被编辑删除,并扣除20分,情节严重者,“百科”有权对其做出关闭部分权限、暂停直至删除其帐号等处罚。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淡定的小Y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值