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;
}

时间: 2024-08-12 14:45:32

BZOJ SCOI 2007 修车 费用流的相关文章

bzoj 1070: [SCOI2007]修车 -- 费用流

1070: [SCOI2007]修车 Time Limit: 1 Sec  Memory Limit: 128 MB Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. Input 第一行有两个m,n,表示技术人员数与顾客数. 接下来n行,每行m个整数.第

BZOJ 2661 连连看(费用流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2661 题意:给出一个区间[a,b]中的全部整数,如果其中某两个数x,y(设x>y)的平方差x^2-y^2是一个完全平方数z^2,并且y与z互质,那么就可以将x和y一起消除,同时得到x+y点分数.要求就是,消除的数对尽可能多的前提下,得到的分数尽量多. 思路:首先暴力出所有合法的数对(x,y).然后将每个用到的数字拆成两个点,每个数对连一条边.最后的答案除以2即可. struct nod

BZOJ 2879 美食节(费用流-动态加边)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2879 题意:有n道菜,每道菜需要b[i]份,m个厨师,第j个厨师做第i道菜需要时间a[i][j],求做完所有菜,所有人等待的最小总时间. 思路:设所有的菜为sum.一个明显的思路是将每个厨师拆成sum个点.然后sum个菜每个菜向每个厨师的每个点连边,表示该道菜为该厨师第几个做.由于这样数据太大.动态加边.每次增光一次后找到此次增广的厨师,每道菜将其连边. struct node { i

BZOJ 1070 修车(费用流)

如果能想到费用流,这道题就是显然了. 要求所有人的等待平均时间最小,也就是所有人的总等待时间最小. 每辆车只需要修一次,所以s连每辆车容量为1,费用为0的边. 现在需要把每个人拆成n个点,把车和每个人的第k个点连一条容量为1,费用为cost[i][j]*k的边. 最后把每个人拆完后的点向汇点连一条容量为1,费用为0的边. #include<iostream> #include<cstdio> #include<cstring> #define inf 0x7ffffff

图论(网络流):SCOI 2007 修车

同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. 输入 第一行有两个数M,N,表示技术人员数与顾客数. 接下来n行,每行m个整数.第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T. 输出 最小平均等待时间,答案精确到小数点后2位. 样例 repair.in 2 2

BZOJ 2424: [HAOI2010]订货 费用流

2424: [HAOI2010]订货 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=2424 Description 某公司估计市场在第i个月对某产品的需求量为Ui,已知在第i月该产品的订货单价为di,上个月月底未销完的单位产品要付存贮费用m,假定第一月月初的库存量为零,第n月月底的库存量也为零,问如何安排这n个月订购计划,才能使成本最低?每月月初订购,订购后

BZOJ 2597 WC2007 剪刀石头布 费用流

题目大意:给出一张竞赛图中的其中几条单向边,剩下的边随意定向.问最多可以形成多少三元环. 思路:对于任意三个点来说,他们组成了三元环,当且仅当这些点的入度=处度 = 1.如果没有组成三元环,只需要改变这其中任意一条边的方向,使得一个点的入度变成2,一个点的出度变成2.我们只需要算出有多少三个点中有一个点的入度为2的就可以了,并最小化这个东西. 通过公式:ans=C(n,3)-ΣC(degree[x],2)可以发现,我们只需要让每个点的入度尽可能小.由此想到费用流模型(我怎么想不到..) 类似于x

BZOJ 1927 星际竞速(费用流)

考虑费用流,题目要求走n个点都走完且恰好一次,显然流量的限制为n. 建立源点s和汇点t,并把每个星球拆成两个点i和i',分别表示已到达该点和经过该点. 对于能力爆发,建边(s,i',1,w). 对应高速航行,建边(s,i,1,0), (i,j',1,w). 因为每个点必须走一次且只能走一次.建边(i',t,1,0). 其实就是类似最小路径覆盖的建图方法. # include <cstdio> # include <cstring> # include <cstdlib>

[BZOJ1070] [SCOI2007] 修车 (费用流 &amp; 动态加边)

Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. Input 第一行有两个m,n,表示技术人员数与顾客数. 接下来n行,每行m个整数.第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T. Output 最小平均等待时间,答案精确到小数点后2位