zoukankan      html  css  js  c++  java
  • _bzoj1061 [Noi2008]志愿者招募【最小费用最大流】

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

    尽管不是mcmf的裸题,但还是保存一下模版叭~

    很好的一道建模的题,把变量间的加加减减等效成网络中的流入流量与流出流量,再带上个权,求个最小费用就好,详细题解间此:https://www.byvoid.com/blog/noi-2008-employee/

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    const int maxn = 1010, maxm = 10005, maxe = 100000;
    const long long inf = 0x3c3c3c3c3c3c3c3cLL;
    
    int n, m, a[maxn], s[maxm], t[maxm], cost[maxm], S, T;
    int head[maxn], to[maxe], next[maxe], from[maxe], lb;
    long long d[maxn], c[maxn], w[maxe], flow[maxe], cap[maxe];
    int p[maxn], que[maxn], head_, tail, h;
    bool inq[maxn];
    
    inline bool spfa(long long & co) {
    	memset(d, 0x3c, sizeof d);
    	head_ = tail = 0;
    	memset(inq, 0, sizeof inq);
    	que[tail++] = S;
    	inq[S] = 1;
    	c[S] = inf;
    	d[S] = 0;
    	while (head_ != tail) {
    		h = que[head_++];
    		inq[h] = 0;
    		if (head_ == T + 3) {
    			head_ = 0;
    		}
    		for (int j = head[h]; j != -1; j = next[j]) {
    			if (cap[j] > flow[j] && d[to[j]] > d[h] + w[j]) {
    				d[to[j]] = d[h] + w[j];
    				c[to[j]] = std::min(c[h], cap[j] - flow[j]);
    				p[to[j]] = j;
    				if (!inq[to[j]]) {
    					que[tail++] = to[j];
    					inq[to[j]] = 1;
    					if (tail == T + 3) {
    						tail = 0;
    					}
    				}
    			}
    		}
    	}
    	if (d[T] == inf) {
    		return false;
    	}
    	co += d[T] * c[T];
    	for (int i = T; i != S; i = from[p[i]]) {
    		flow[p[i]] += c[T];
    		flow[p[i] ^ 1] -= c[T];
    	}
    	return true;
    }
    inline long long mcmf(void) {
    	long long co = 0;
    	while (spfa(co));
    	return co;
    }
    
    inline void ist(int aa, int ss, long long ww, long long ca) {
    	to[lb] = ss;
    	from[lb] = aa;
    	next[lb] = head[aa];
    	head[aa] = lb;
    	w[lb] = ww;
    	cap[lb] = ca;
    	++lb;
    	
    	to[lb] = aa;
    	from[lb] = ss;
    	next[lb] = head[ss];
    	head[ss] = lb;
    	w[lb] = -ww;
    	cap[lb] = 0;
    	++lb;
    }
    
    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 + 2;
    	for (int i = 1; i <= n; ++i) {
    		scanf("%d", a + i);
    	}
    	for (int i = 1; i <= m; ++i) {
    		scanf("%d%d%d", s + i, t + i, cost + i);
    	}
    	
    	for (int i = 1; i <= n + 1; ++i) {
    		if (a[i - 1] - a[i] >= 0) {
    			ist(S, i, 0, (long long)(a[i - 1] - a[i]));
    		}
    		else {
    			ist(i, T, 0, (long long)(a[i] - a[i - 1]));
    		}
    	}
    	for (int i = 1; i <= m; ++i) {
    		ist(t[i] + 1, s[i], (long long)cost[i], inf);
    	}
    	for (int i = 1; i <= n; ++i) {
    		ist(i, i + 1, 0, inf);
    	}
    	printf("%lld
    ", mcmf());
    	return 0;
    }
    

      

  • 相关阅读:
    unity 反编译 step2 dll -->reflector
    unity 反编译 step1 disUnity
    rpg
    cmake使用
    linux mysqld的启动过程
    unity内存加载和释放
    Linux下MySql数据库常用操作
    MySQL主从复制与读写分离(非原创,谢绝膜拜)
    linux下IPTABLES配置详解
    linux下查看端口的占用情况
  • 原文地址:https://www.cnblogs.com/ciao-sora/p/6180699.html
Copyright © 2011-2022 走看看