• _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;
    }
    

      

  • 相关阅读:
    from import 的认识
    模块初识
    eq方法
    hash介绍
    item系列
    析构函数
    serializers进阶
    APIView源码解析
    RPC协议
    面试题补充
  • 原文地址:https://www.cnblogs.com/ciao-sora/p/6183023.html
Copyright © 2020-2023  润新知