zoukankan      html  css  js  c++  java
  • [SCOI 2007] 修车

    题目

    传送门

    解法

    首先平均等待时间最小就是总等待时间最小。

    对于一位师傅,如果他修了 (s) 辆车,第 (i) 个被修的车为 (p_i),修车时间为 (t_i)。那么第 (i) 辆车的等待时间为第 (i) 辆车的等待时间 (+t_i)。那么 (s) 辆车的总时间就是 (sum_{i=1}^s t_i imes (s-i+1))

    但这样还是不好做,因为 (t_i) 的系数和 (s) 挂钩。

    我们可以修改一下定义:设倒数第 (i) 个被修的车为 (p_i),修车时间为 (t_i)。那么 (s) 辆车的总时间就是 (sum_{i=1}^s t_i imes i)

    接下来考虑如何建图。

    1. 首先对于每辆车,由于只能被修一次,从 (S) 连一条容量为 (1),边权为 (0) 的边。
    2. 每个师傅 (j) 拆成 (n) 个点(拆的点向 (T) 连一条容量为 (1),边权为 (0) 的边),表示修 (i) 辆车,枚举修的第 (i) 辆车 (k),则 (k) 向点连容量为 (1),边权为 (T_{k,j} imes i) 的边。

    跑最小费用最大流即可。

    考虑正确性。最大流肯定能保证 (S) 向车的边满流,并且师傅的修车序列连续(即不会修第 (1) 辆车后修第 (3) 辆车)因为系数 (2<3),这个由最小费用保证。

    代码

    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #define Pair pair <int, int>
    using namespace std;
    
    const int N = 66, M = 1e5, lim = 0x3f3f3f3f,maxn=700;
    int a[N][N], prev[maxn], pree[maxn], dis[maxn], s, t, n, m, cnt, val[M], flow[M], to[M], head[maxn], nxt[M], h[maxn];
    
    inline int read() {
        int x = 0, f = 1;
        char s = getchar();
        while(! isdigit(s)) {
            if(s == '-')
                f = -1;
            s = getchar();
        }
        while(isdigit(s)) {
            x = (x << 1) + (x << 3) + (s ^ 48);
            s = getchar();
        }
        return x * f;
    }
    
    inline void print(int x) {
        if(x < 0) {
            putchar('-');
            x = -x;
        }
        if(x > 9)
            print(x / 10);
        putchar(x % 10 + '0');
    }
    
    inline int Min(const int x, const int y) {
    	if(x < y)
    		return x;
    	return y;
    }
    
    inline void addEdge(const int u, const int v, const int w) {
    	to[++ cnt] = v;
    	nxt[cnt] = head[u];
    	flow[cnt] = 1;
    	val[cnt] = w;
    	head[u] = cnt;
    	to[++ cnt] = u;
    	nxt[cnt] = head[v];
    	flow[cnt] = 0;
    	val[cnt] = -w;
    	head[v] = cnt;
    }
    
    int EK() {
    	int res = 0, maxflow;
    	while(1) {
    		priority_queue <Pair, vector <Pair>, greater <Pair> > q;
    		memset(dis, 0x3f, sizeof dis);
    		dis[s] = 0;
    		q.push(Pair(0, s));
    		while(! q.empty()) {
    			Pair now = q.top();
    			q.pop();
    			int u = now.second;
    			if(dis[u] < now.first)
    				continue;
    			for(int i = head[u]; ~i; i = nxt[i]) {
    				int v = to[i];
    				if(flow[i] > 0 && dis[v] > dis[u] + val[i] + h[u] - h[v]) {
    					dis[v] = dis[u] + val[i] + h[u] - h[v];
    					prev[v] = u;
    					pree[v] = i;
    					q.push(Pair(dis[v], v));
    				}
    			}
    		}
    		if(dis[t] == lim)
    			break;
    		maxflow = lim;
    		for(int i = t; i != s; i = prev[i])
    			maxflow = Min(maxflow, flow[pree[i]]);
    		res += maxflow * (dis[t] - h[s] + h[t]);
    		for(int i = t; i != s; i = prev[i]) {
    			flow[pree[i]] -= maxflow;
    			flow[pree[i] ^ 1] += maxflow;
    		}
    		for(int i = 0; i <= m * n; ++ i)
    			h[i] += dis[i];
    	}
    	return res;
    }
    
    int pos(const int i, const int j) {
    	return (i - 1) * n + j;
    }
    
    int main() {
    	m = read();
    	n = read();
    	cnt = 1;
    	s = 0;
    	t = m*n+n+1;
    	memset(head, -1, sizeof head);
    	for(int i = 1; i <= n; ++ i)
    		for(int j = 1; j <= m; ++ j)
    			a[i][j] = read();
    	for(int i = 1; i <= m; ++ i)
    		for(int j = 1; j <= n; ++ j) {
    			for(int k = 1; k <= n; ++ k)
    				addEdge(m * n + k, pos(i, j), j * a[k][i]);
    			addEdge(pos(i, j), t, 0);
    		}
    	for(int i = 1; i <= n; ++ i)
    		addEdge(s, m * n + i, 0);
    	printf("%.2f
    ", EK() * 1.0 / (n * 1.0));
    	return 0;
    }
    
  • 相关阅读:
    byte b=1、b=b+1、b+=1
    parameter ‘0’ not found
    Java设计模式—Singleton
    EL JSTL(得劲)
    天网恢恢Filter 窃听风云Listener
    Jsp学习总结(二)
    Jsp学习总结(一)
    Bugs(识破)
    [PAT乙级] Practise 1016 部分A+B
    [PAT乙级] Practise 1015 德才论
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/14403890.html
Copyright © 2011-2022 走看看