• 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
    ", ++kase);
    		rep(i,1,n) {
    		  rep(j,n+1,n+m)
    		  	printf("%d ", e[id[i][j]].flow+1);
    		  puts("");
    		}
    		puts("");
    	}
    
    	return 0;
    }


  • 相关阅读:
    如何利用 iTunes 把 m4a/wav 文件转成 MP3 格式
    The best way to learn a programming language
    琼瑶哀悼丈夫去世
    与“芯片”相关的专业有哪些?
    君子使物,不为物使
    SRID (空间引用识别号, 坐标系)【转】
    编码
    test
    剪贴板神器:Ditto
    写Markdown博客时遇到的一些问题
  • 原文地址:https://www.cnblogs.com/yearwhk/p/5119877.html
Copyright © 2020-2023  润新知