zoukankan      html  css  js  c++  java
  • 洛谷P3980 [NOI2008]志愿者招募

    题解

    最小费用最大流

    每一天是一条边((inf-a[i], 0))

    然后对于一类志愿者,

    区间两端连一条((inf, c[i]))

    (S)向第一个点连((inf, 0))

    最后一个点向(T)((inf, 0))

    然后跑最小费用最大流

    这为什么是对的?

    我们的目的变成用加的那些边,把最大流量填成(inf)

    求最小费用

    Code

    #include<bits/stdc++.h>
    
    #define LL long long
    #define RG register
    
    using namespace std;
    template<class T> inline void read(T &x) {
    	x = 0; RG char c = getchar(); bool f = 0;
    	while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;
    	while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();
    	x = f ? -x : x;
    	return ;
    }
    template<class T> inline void write(T x) {
    	if (!x) {putchar(48);return ;}
    	if (x < 0) x = -x, putchar('-');
    	int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;
    	for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
    }
    const int N = 2010, inf = 2147483647;
    int a[N];
    
    struct node {
    	int to, nxt, w, v;
    }g[2000000];
    int last[N], gl = 1;
    void add(int x, int y, int w, int v) {
    	g[++gl] = (node) {y, last[x], w, v};
    	last[x] = gl;
    	g[++gl] = (node) {x, last[y], 0, -v};
    	last[y] = gl;
    }
    
    int s, t;
    
    int dis[N], from[N], pre[N];
    bool vis[N];
    queue<int> q;
    
    bool spfa() {
    	q.push(s);
    	memset(dis, 127, sizeof(dis));
    	dis[s] = 0;
    	while (!q.empty()) {
    		int u = q.front(); q.pop();
    		for (int i = last[u]; i; i = g[i].nxt) {
    			int v = g[i].to;
    			if (dis[v] > dis[u] + g[i].v && g[i].w) {
    				dis[v] = dis[u] + g[i].v;
    				from[v] = i; pre[v] = u;
    				if (!vis[v]) {
    					vis[v] = 1;
    					q.push(v);
    				}
    			}
    		}
    		vis[u] = 0;
    	}
    	return dis[0] != dis[t];
    }
    
    
    int McMf() {
    	int ans = 0;
    	while (spfa()) {
    		int di = inf;
    		for (int i = t; i != s; i = pre[i]) di = min(di, g[from[i]].w);
    		ans  += di * dis[t];
    		for (int i = t; i != s; i = pre[i])
    			g[from[i]].w -= di, g[from[i]^1].w += di;
    	}	
    	return ans;
    }
    
    int main() {
    	int n, m;
    	read(n), read(m);
    	for (int i = 1; i <= n; i++) read(a[i]);
    	s = n + 2, t = s + 1;
    	for (int i = 1; i <= n; i++)
    		add(i, i+1, inf - a[i], 0);
    	add(s, 1, inf, 0), add(n + 1, t, inf, 0);
    	for (int i = 1; i <= m; i++) {
    		int S, T, C;
    		read(S), read(T), read(C);
    		add(S, T+1, inf, C);
    	}
    	printf("%d
    ", McMf());
    	return 0;
    }
    
    
  • 相关阅读:
    # 漏洞挖掘技巧清单 #
    CVE-2020-0796——SMBV3客户端/服务端远程代码执行漏洞(远程代码执行+权限提升)
    SSH公钥详细介绍及拓展
    滑动窗口(数据结构)
    反素数解析
    树状数组的基本操作
    Rochambeau POJ
    一般图最大匹配
    2020牛客暑期多校训练营(第一场)H Minimum-cost Flow
    A Bug's Life POJ
  • 原文地址:https://www.cnblogs.com/zzy2005/p/10478226.html
Copyright © 2011-2022 走看看