UVa 11082 - 最大流 基础建模

一道很基础的网络流建模。。

本题输入的是前缀和,先用它们求出每行、每列的元素和

然后将每一行看作一个节点(记作Xi),每一列看作一个节点(记作Yi),并新增源点S、汇点T。

S往Xi连边,容量为这一行的元素和减1;

Yi往T连边,容量同上。

每个Xi往每个Yj连边,容量为20-1=19。

之所以要将容量都减1,是因为边权要在1~20之间,有下界,但并不需要用到专门的有下界最大流算法,可以直接先减1,求出结果后再加1。

跑一遍最大流。当且仅当所有S出边和T入边都满载时有解。元素Aij的值即为Xi -> Yj的流量+1。

模板用的是Rujia Liu的。。可读性很强,但效率不是很高。。下次把黄学长的模板学过来。。

(最近刷题速度下降。。再这样下去药丸。。

// UVa11082

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

 const int M=2000, N=100, INF=0x3f3f3f3f;

 #define rep(i,a,b) for (int i=a; i<=b; i++)
 #define read(x) scanf("%d", &x)

 struct Edge{
 	int from, to, pre, cap, flow;
 }e[M];

 int p, pre[N];
 void ine(int from, int to, int cap, int flow) {
 	e[p].from=from; e[p].to=to; e[p].cap=cap; e[p].pre=pre[from]; e[p].flow=flow; pre[from]=p;
 	p++;
 }
 #define reg(i,x) for (int i=pre[x]; i!=-1; i=e[i].pre)

 void Add_Edge(int from, int to, int cap) {
 	ine(from, to, cap, 0);
 	ine(to, from, 0, 0);
 }

 int n, m, s, t, a[N], last, tot, edges, nodes, id[N][N], kase=0, T, cur[N], d[N];
 bool vis[N];

 void init() {
 	p=0;
 	rep(i,1,edges) e[i].pre=-1;
 	rep(i,1,nodes) pre[i]=-1;
 }

 int Q[2*N];
 bool BFS() {
 	memset(vis, 0, sizeof(vis));
 	int head=1, tail=1;
 	Q[1]=s; d[s]=0; vis[s]=true;
 	while (head<=tail) {
 		int x=Q[head++];
 		reg(i,x) {
 			int y=e[i].to;
 			if (!vis[y] && e[i].cap>e[i].flow) {
 				vis[y]=true;
 				d[y]=d[x]+1;
 				Q[++tail]=y;
 			}
 		}
 	}
 	return vis[t];
 }

 int DFS(int x, int a) {  // a表示“目前为止所有弧的最小残量”
 	if (x==t || a==0) return a;
 	int flow=0, f;
 	for (int &i=cur[x]; i!=-1; i=e[i].pre) {
 		if (d[x]+1==d[e[i].to] && (f=DFS(e[i].to, min(a, e[i].cap-e[i].flow)))>0) {
 			flow+=f;			
 			a-=f;  // Why can we do this?
 			e[i].flow+=f;
 			e[i^1].flow-=f;
 			if (a==0) break;
 		}
 	}
 	return flow;
 }

 void Dinic() {
 	int flow=0;
 	while (BFS()) {
 		rep(i,1,n+m+2) cur[i]=pre[i];
 		flow+=DFS(s, INF);
 	}
 }

int main()
{
	read(T);
	while (T--) {

		read(n); read(m);
		edges=n*m*2+n+m+5;
		nodes=n+m+5;
		init();

		read(tot); a[1]=tot;
		rep(i,2,n) last=tot, read(tot), a[i]=tot-last;
		read(tot); a[n+1]=tot;
		rep(i,n+2,n+m) last=tot, read(tot), a[i]=tot-last;

		s=n+m+1, t=n+m+2;
		rep(i,1,n) Add_Edge(s, i, a[i]-m);
		rep(i,n+1,m+n) Add_Edge(i, t, a[i]-n);

		rep(i,1,n) 
		  rep(j,n+1,n+m) {
		    Add_Edge(i, j, 19);
		    id[i][j]=p-2;
		  }

		Dinic();

		printf("Matrix %d\n", ++kase);
		rep(i,1,n) {
		  rep(j,n+1,n+m)
		  	printf("%d ", e[id[i][j]].flow+1);
		  puts("");
		}
		puts("");
	}

	return 0;
}


posted @ 2015-12-15 23:52  Armeria  阅读(155)  评论(0编辑  收藏  举报