BZOJ1070:[SCOI2007]修车
? 解题记录 ? ? BZOJ ? ? 网络流 ? ? 费用流 ?    2018-08-13 10:51:41    317    0    0

【题目描述】

同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。

【输入】

第一行有两个m,n,表示技术人员数与顾客数。 接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。

【输出】

最小平均等待时间,答案精确到小数点后2位。

【输入样例】

2 2
3 2
1 4

【输出样例】

1.50

【提示】

数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)

【来源】

没有写明来源

神奇的网络流题目。考虑:让第i辆车成为第j个修理工修理的第k辆,对答案的贡献。但是因为我们不知道这个修理工之后还有多少车要修,我们没有办法统计贡献。这是,我们不妨用逆向思维:我们让第i辆车成为第j个修理工修理的倒数第k辆,这样我们就知道这辆车被修后对答案的贡献了。于是我们把修理工拆成车辆那么多个点,表示倒数第k辆修的车就行了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
struct edge {
	int v, w, cost, next;
}e[maxn << 2];
int head[maxn], cnt, n, m, ndcnt, S, T;
void adde(const int &u, const int &v, const int &w, const int &cost) {
	e[cnt] = (edge) {v, w, cost, head[u]};
	head[u] = cnt++;
	e[cnt] = (edge) {u, 0, -cost, head[v]};
	head[v] = cnt++;
}
int worker[105][105], car[105], tm[105][105];

queue<int > q;
int vis[maxn], dis[maxn], fa[maxn], id[maxn];
int SPFA(int s, int t) {
	memset(dis, 0x3f, sizeof(int) * (ndcnt + 5));
	dis[s] = 0, q.push(s);
	while(!q.empty()) {
		int u = q.front(), v;q.pop(), vis[u] = 0;
		for(register int i = head[u]; ~i; i = e[i].next) {
			v = e[i].v;
			if(!e[i].w) continue;
			if(dis[v] > dis[u] + e[i].cost) {
				id[v] = i, fa[v] = u;
				dis[v] = dis[u] + e[i].cost;
				if(vis[v]) continue;
				vis[v] = 1, q.push(v);
			}
		}
	}
	return dis[t] == inf ? -1 : dis[t];
}

int fdmn(int s, int u) {
	if(u == s) return inf;
	return min(e[id[u]].w, fdmn(s, fa[u]));
}

void ext(int s, int u, int w) {
	if(u == s) return ;
	e[id[u]].w -= w, e[id[u] ^ 1].w += w;
	ext(s, fa[u], w);
}

int Minflow(int s, int t) {
	int ans = 0, now = 0, mn;
	while(1) {
		now = SPFA(s, t);
		if(now == -1) break;
		ans += now * (mn = fdmn(s, t));
		ext(s, t, mn);
	}
	return ans;
}

int main() {
	memset(head, -1, sizeof(head));
	scanf("%d%d", &m, &n), S = ++ndcnt, T = ++ndcnt;
	for(register int i = 1; i <= n; ++i)
		for(register int j = 1; j <= m; ++j)
			scanf("%d", &tm[i][j]);
	for(register int i = 1; i <= n; ++i)
		for(register int j = 1; j <= m; ++j)
			worker[j][i] = ++ndcnt, adde(ndcnt, T, 1, 0);
	for(register int i = 1; i <= n; ++i) {
		car[i] = ++ndcnt, adde(S, ndcnt, 1, 0);
		for(register int j = 1; j <= n; ++j) {
			for(register int k = 1; k <= m; ++k)
				adde(car[i], worker[k][j], 1, tm[i][k] * j);
		}
	}
	printf("%.2lf", (double)Minflow(S, T) / n);
	return 0;
}

 

上一篇: BZOJ2178:圆的面积并

下一篇: HDU 5730 Shell Necklace

317 人读过
立即登录, 发表评论.
没有帐号? 立即注册
0 条评论
文档导航