• BZOJ1927 [Sdoi2010]星际竞速


    题目大意:自己看中文。


    思路:不难发现,题目等价于让我们求出一些标号上升的子序列精确覆盖全集。每个子序列的起点一定是利用“能力爆发”   得到的。

    那么我们仅仅需对于每一个星球,确定一个前驱就能够了。

    若是0作为前驱。则转移代价为定位时间;否则转移代价为路径长度。

    此外一个点的前驱的标号严格小于自己的标号。

    注意0能够作为多个星球的前驱,剩下的星球仅仅能作为一个星球的前驱。

    于是转化为类二分图最优匹配问题,利用最小费用流求解就可以。


    Code:

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    queue<int> q;
    
    #define N 810
    struct Solver {
    	int head[N<<1], next[N*N], end[N*N], flow[N*N], cost[N*N], ind;
    	int d[N<<1], ld[N<<1], lb[N<<1];
    	bool inq[N<<1];
    	void reset() {
    		ind = 0;
    		memset(head, -1, sizeof head);
    	}
    	void addedge(int a, int b, int _flow, int _cost) {
    		int q = ind++;
    		end[q] = b;
    		next[q] = head[a];
    		head[a] = q;
    		flow[q] = _flow;
    		cost[q] = _cost;
    	}
    	void make(int a, int b, int _flow, int _cost) {
    		addedge(a, b, _flow, _cost);
    		addedge(b, a, 0, -_cost);
    	}
    	bool spfa(int S, int T) {
    		memset(d, 0x3f, sizeof d);
    		d[S] = 0;
    		inq[S] = 1;
    		q.push(S);
    		int i, j;
    		while(!q.empty()) {
    			i = q.front();
    			q.pop();
    			inq[i] = 0;
    			for(j = head[i]; j != -1; j = next[j]) {
    				if (flow[j] && d[end[j]] > d[i] + cost[j]) {
    					d[end[j]] = d[i] + cost[j];
    					ld[end[j]] = i;
    					lb[end[j]] = j;
    					if (!inq[end[j]])
    						inq[end[j]] = 1, q.push(end[j]);
    				}
    			}
    		}
    		return d[T] != 0x3f3f3f3f;
    	}
    	int Mincost(int S, int T) {
    		int res = 0, Min, i;
    		while(spfa(S, T)) {
    			Min = 0x3f3f3f3f;
    			for(i = T; i != S; i = ld[i])
    				Min = Min > flow[lb[i]] ? flow[lb[i]] : Min;
    			for(i = T; i != S; i = ld[i])
    				flow[lb[i]] -= Min, flow[lb[i] ^ 1] += Min;
    			res += Min * d[T];
    		}
    		return res;
    	}
    }G;
    
    int main() {
    	
    	int n, m;
    	scanf("%d%d", &n, &m);
    	
    	register int i;
    	int x;
    	G.reset();
    	for(i = 1; i <= n; ++i) {
    		scanf("%d", &x);
    		G.make(1, i<<1^1, 1, x);
    	}
    	
    	int a, b;
    	for(i = 1; i <= m; ++i) {
    		scanf("%d%d%d", &a, &b, &x);
    		if (a > b)
    			swap(a, b);
    		G.make(a<<1, b<<1^1, 1, x);
    	}
    	
    	G.make(0, 1, 0x3f3f3f3f, 0);
    	for(i = 1; i <= n; ++i)
    		G.make(0, i<<1, 1, 0), G.make(i<<1^1, 2*n+2, 1, 0);
    	
    	printf("%d
    ", G.Mincost(0, 2*n+2));
    	
    	return 0;
    }


  • 相关阅读:
    项目编写,寻找项目
    BP优化
    python hook的使用
    BN归一化
    mnist数据集使用torch进行卷积训练
    dropout
    Flip String to Monotone Increasing
    Reach a Number
    wordLadder i/ii
    Palindrome Partitioning II
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/6748257.html
Copyright © 2020-2023  润新知