zoukankan      html  css  js  c++  java
  • Modular Production Line (MCMF)

    Modular Production Line

    [Time Limit: 1000msquad Memory Limit: 65536kB ]

    题意

    给出 (N) 种零件,现在你可以用连续的一些零件组装成为一个产品,组装完你可以获得 (w) 的价值,要求每种零件最多使用 (K) 次并且每一个产品只能生产一个。问你最多可以获得的价值是多少。

    思路

    由于给出的 (N) 很大, (M)很小,那么显然,很多点都是没有用的,那么我们就可以将他们舍弃掉,只使用出现的点,那么可以考虑到离散化。

    • 对于给出的每一个区间 (left[u, v ight]) 内的零件,我们可以从 (u)(v+1) 建一条流量为(1),费用为 (-w) 的边,表示制作了这一个产品的情况。
    • 对于全部的点,我们可以建一条从 (i)(i+1) 的边,表示第 (i) 个零件不使用的情况。
    • 对于超级源点和超级汇点,我们建一条从超级源点到第一个点,流量为 (K),费用为 (0) 的边,在建一条从最后一个点到超级汇点,流量为 (K),费用为 (0) 的边,这是为了防止任意一种零件使用次数超过 (K),所以从一开始就限制了流量。

    最后跑最小费用最大流,算出的答案的绝对值就是要求的。

    #include <map>
    #include <set>
    #include <list>
    #include <ctime>
    #include <cmath>
    #include <stack>
    #include <queue>
    #include <cfloat>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <bitset>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define  lowbit(x)  x & (-x)
    #define  mes(a, b)  memset(a, b, sizeof a)
    #define  fi         first
    #define  se         second
    #define  pii        pair<int, int>
    #define  INOPEN     freopen("in.txt", "r", stdin)
    #define  OUTOPEN    freopen("out.txt", "w", stdout)
    
    typedef unsigned long long int ull;
    typedef long long int ll;
    const int    maxn = 5e2 + 10;
    const int    maxm = 1e4 + 10;
    const ll     mod  = 1e9 + 7;
    const ll     INF  = 1e18 + 100;
    const int    inf  = 0x3f3f3f3f;
    const double pi   = acos(-1.0);
    const double eps  = 1e-8;
    using namespace std;
    
    int n, m, k;
    int cas, tol, T;
    
    struct Node{
    	int u, v;
    	int w, val;
    	int next;
    } node[maxm];
    int head[maxn];
    int pre[maxn], dis[maxn], cap[maxn], vis[maxn];
    
    void addnode(int u, int v, int w, int val) {
    	node[tol].u = u;
    	node[tol].v = v;
    	node[tol].w = w;
    	node[tol].val = val;
    	node[tol].next = head[u];
    	head[u] = tol++;
    }
    
    bool spfa(int src, int des, int &flow, int &cost) {
    	mes(pre, 0), mes(dis, inf), mes(cap, 0), mes(vis, false);
    	queue<int> q;
    	while(!q.empty())	q.pop();
    	pre[src] = src;
    	vis[src] = true;
    	cap[src] = inf;
    	dis[src] = 0;
    	q.push(src);
    	while(!q.empty()) {
    		int u = q.front();
    		q.pop();
    		vis[u] = false;
    		for(int i=head[u]; ~i; i=node[i].next) {
    			int v = node[i].v;
    			if(node[i].w && dis[v] > dis[u]+node[i].val) {
    				dis[v] = dis[u]+node[i].val;
    				cap[v] = min(cap[u], node[i].w);
    				pre[v] = i;
    				if(!vis[v]) {
    					vis[v] = true;
    					q.push(v);
    				}
    			}
    		}
    	}
    	if(dis[des] == inf)	return false;
    	flow += cap[des];
    	cost += cap[des] * dis[des];
    	int u = des;
    	while(u != src) {
    		node[pre[u]].w -= cap[des];
    		node[pre[u]^1].w += cap[des];
    		u = node[pre[u]].u;
    	}
    	return true;
    }
    
    int MCMF(int src, int des) {
    	int flow = 0, cost = 0;
    	while(spfa(src, des, flow, cost));
    	return cost;
    }
    
    vector<int> vv;
    vector<pair <pair<int, int>, int> > vec;
    
    int getid(int x) {
    	return lower_bound(vv.begin(), vv.end(), x) - vv.begin() + 1;
    }
    
    void init() {
    	tol = 0;
    	vv.clear();
    	vec.clear();
    	mes(head, -1);
    }
    
    int main() {
    	scanf("%d" ,&T);
    	while(T--) {
    		init();
    		scanf("%d%d%d", &n, &k, &m);
    		for(int i=1, u, v, w; i<=m; i++) {
    			scanf("%d%d%d", &u, &v, &w);
    			vec.push_back(make_pair(make_pair(u, v), w));
    			vv.push_back(u);
    			vv.push_back(v);
    		}
    		sort(vv.begin(), vv.end());
    		vv.erase(unique(vv.begin(), vv.end()), vv.end());
    		int src = 0, des = vv.size() + 2;
    		for(int i=1; i<=vv.size(); i++) {
    			addnode(i, i+1, inf, 0);
    			addnode(i+1, i, 0, 0);
    //			printf("%d %d %d %d
    ", i, i+1, inf, 0);
    		}
    		addnode(src, 1, k, 0);
    		addnode(1, src, 0, 0);
    //		printf("%d %d %d %d
    ", src, 1, k, 0);
    		addnode(vv.size()+1, vv.size()+2, k, 0);
    		addnode(vv.size()+2, vv.size()+1, 0, 0);
    //		printf("%d %d %d %d
    ", vv.size()+1, vv.size()+2, k, 0);
    		for(auto i : vec) {
    			int u = i.fi.fi, v = i.fi.se, w = i.se;
    			u = getid(u);
    			v = getid(v);
    			addnode(u, v+1, 1, -w);
    			addnode(v+1, u, 0, w);
    //			printf("%d %d %d %d
    ", u, v+1, 1, -w);
    		}
    		int ans = -MCMF(src, des);
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    八枚硬币问题
    找出诡异的Bug:数据怎么存不进去
    IKAnalyzer使用停用词词典进行分词
    【Quick-COCOS2D-X 3.3 怎样绑定自己定义类至Lua之四】使用绑定C++至Lua的自己定义类
    iOS 自我检測
    蓝桥杯 BASIC 29 高精度加法(大数)
    二叉树的非递归遍历
    [算法]有趣算法合辑[11-20]
    习惯的力量之四理直气壮的借口?
    《github一天一道算法题》:分治法求数组最大连续子序列和
  • 原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/10904346.html
Copyright © 2011-2022 走看看