首页 > 代码库 > BZOJ SCOI 2007 修车 费用流

BZOJ SCOI 2007 修车 费用流

题目大意:有一些车和一些修车的人,给出每个人修每个车的时间,问所有人等待的最短平均时间是多少。


思路:记得POJ有一个和这个很像的题,做法是一样的。对于每个人修车的时候,我们只考虑他修车的时间对在它之后修车的人的时间的影响,因此我们只要考虑每一辆车是倒数第几个修的就可以了,然后朴素的建图,跑朴素的费用流,就可以过。


CODE:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define MAX 800
#define MAXE 100010
#define INF 0x3f3f3f3f
#define S 0
#define T (MAX - 1)
using namespace std;

int shopper,cars;
int src[MAX][MAX];

int head[MAX],total = 1;
int next[MAXE],aim[MAXE],cost[MAXE],flow[MAXE];

int f[MAX],from[MAX],p[MAX];
bool v[MAX];

inline void Add(int x,int y,int f,int c)
{
	next[++total] = head[x];
	aim[total] = y;
	flow[total] = f;
	cost[total] = c;
	head[x] = total;
}

inline void Insert(int x,int y,int f,int c)
{
	Add(x,y,f,c);
	Add(y,x,0,-c);
}

inline bool SPFA()
{
	static queue<int> q;
	while(!q.empty())	q.pop();
	q.push(S);
	memset(v,false,sizeof(v));
	memset(f,0x3f,sizeof(f));
	f[S] = 0;	
	while(!q.empty()) {
		int x = q.front(); q.pop();
		v[x] = false;
		for(int i = head[x]; i; i = next[i])
			if(flow[i] && f[aim[i]] > f[x] + cost[i]) {
				f[aim[i]] = f[x] + cost[i];
				if(!v[aim[i]]) {
					v[aim[i]] = true;
					q.push(aim[i]);
				}
				from[aim[i]] = x;
				p[aim[i]] = i;
			}
	}
	return f[T] != INF;
}

int EdmondsKarp()
{
	int re = 0;
	while(SPFA()) {
		int remain_flow = INF;
		for(int i = T; i != S; i = from[i])
			remain_flow = min(remain_flow,flow[p[i]]);
		for(int i = T; i != S; i = from[i]) {
			flow[p[i]] -= remain_flow;
			flow[p[i]^1] += remain_flow;
		}
		re += remain_flow * f[T];
	}
	return re;
}

int main()
{
	cin >> shopper >> cars;
	for(int i = 1; i <= cars; ++i)
		for(int j = 1; j <= shopper; ++j)
			scanf("%d",&src[i][j]);
	for(int i = 1; i <= cars; ++i)
		Insert(S,i,1,0);
	for(int i = 1; i <= cars; ++i)
		for(int j = 1; j <= shopper; ++j)
			for(int k = 1; k <= cars; ++k) 
				Insert(i,j * cars + k,1,src[i][j] * k);
	for(int i = 1; i <= shopper; ++i)
		for(int j = 1; j <= cars; ++j)
			Insert(i * cars + j,T,1,0);
	cout << fixed << setprecision(2) << (double)EdmondsKarp() / cars << endl;
	return 0;
}


BZOJ SCOI 2007 修车 费用流