zoukankan      html  css  js  c++  java
  • _bzoj1497 [NOI2006]最大获利【最大权闭合子图】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1497

    保存最大流模版。

    选一个用户群,就必须要选对应的两个中转站,这种关系类似“最大全闭合子图”的关系,因此构图,求最小割。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    const int maxn = 5005, maxm = 50005, maxe = 400000;
    
    int n, m, t1, t2, t3, S, T, ans;
    int head[maxn + maxm], to[maxe], next[maxe], from[maxe], cap[maxe], flow[maxe], lb;
    int d[maxn + maxm], que[maxn + maxm], head_, tail, h, num[maxn + maxm], p[maxn + maxm];
    
    inline void ist(int aa, int ss, int ca) {
    	to[lb] = ss;
    	from[lb] = aa;
    	next[lb] = head[aa];
    	head[aa] = lb;
    	cap[lb] = ca;
    	++lb;
    	
    	to[lb] = aa;
    	from[lb] = ss;
    	next[lb] = head[ss];
    	head[ss] = lb;
    	cap[lb] = 0;
    	++lb;
    }
    inline int lbl(int i) {
    	int rt = T;
    	for (int j = head[i]; j != -1; j = next[j]) {
    		if (cap[j] > flow[j]) {
    			rt = std::min(rt, d[to[j]]);
    		}
    	}
    	return rt + 1;
    }
    inline int fnd(int i) {
    	for (int j = head[i]; j != -1; j = next[j]) {
    		if (d[i] == d[to[j]] + 1 && cap[j] > flow[j]) {
    			return j;
    		}
    	}
    	return -1;
    }
    inline int maxflow(void) {
    	int rt = 0, delta;
    	int i = S, j, x;
    	while (d[S] <= T) {
    		j = fnd(i);
    		if (j != -1) {
    			p[to[j]] = j;
    			i = to[j];
    			if (i == T) {
    				delta = 2147483647;
    				for (; i != S; i = from[p[i]]) {
    					delta = std::min(delta, cap[p[i]] - flow[p[i]]);
    				}
    				for (i = T; i != S; i = from[p[i]]) {
    					flow[p[i]] += delta;
    					flow[p[i] ^ 1] -= delta;
    				}
    				rt += delta;
    			}
    		}
    		else {
    			x = lbl(i);
    			if (--num[d[i]] == 0) {
    				return rt;
    			}
    			++num[d[i] = x];
    			if (i != S) {
    				i = from[p[i]];
    			}
    		}
    	}
    	return rt;
    }
    
    int main(void) {
    	//freopen("in.txt", "r", stdin);
    	memset(head, -1, sizeof head);
    	memset(next, -1, sizeof next);
    	scanf("%d%d", &n, &m);
    	T = n + m + 1;
    	
    	for (int i = 1; i <= n; ++i) {
    		scanf("%d", &t3);
    		ist(S, i, t3);
    	}
    	for (int i = n + 1; i <= n + m; ++i) {
    		scanf("%d%d%d", &t1, &t2, &t3);
    		ans += t3;
    		ist(i, T, t3);
    		ist(t1, i, 0x3c3c3c3c);
    		ist(t2, i, 0x3c3c3c3c);
    	}
    	
    	memset(d, 0x3c, sizeof d);
    	d[T] = 0;
    	que[tail++] = T;
    	while (head_ != tail) {
    		h = que[head_++];
    		++num[d[h]];
    		for (int j = head[h]; j != -1; j = next[j]) {
    			if ((j & 1) && d[to[j]] == 0x3c3c3c3c) {
    				d[to[j]] = d[h] + 1;
    				que[tail++] = to[j];
    			}
    		}
    	}
    	printf("%d
    ", ans - maxflow());
    	return 0;
    }
    

      

  • 相关阅读:
    WPF控件操作之改变父控件之TabControl示例
    WPF里面的DockPanel的Fill去哪了,如何填满整个空间
    [原创]winform自定义控件之类属性-多重属性-可折叠属性
    WinForm之DataBinding
    WinForm自定义控件之DefaultValue的误解
    code snippet:依赖属性propa的小技巧
    【原创】WinForm中实现单独Time控件的方式
    node.js安装本地模块遇到的目录锁定问题【新手问题】
    《程序员思维修炼》之德雷福斯模型
    IOptions、IOptionsMonitor以及IOptionsSnapshot
  • 原文地址:https://www.cnblogs.com/ciao-sora/p/6183023.html
Copyright © 2011-2022 走看看