LUOGU 2053 [SCOI2007] repair the minimum cost maximum flow

Creative Commons License Copyright: Attribution, allow others to create paper-based, and must distribute paper (based on the original license agreement with the same license Creative Commons )

title

LUOGU 2053
Title Description

The same time there are N car owners with their car came to a car repair center. M service center has technical staff, technical staff of various different car repair time used is different. Now we need to arrange this M bit of skill in the repair of cars and order so that the average customer wait time to a minimum.
Description: Customer wait time is the time the service is completed with from his car to a service center to.

Input and output format
input format:

The first line has two numbers M, N, and the number represents the number of customers in the art.
Next n lines of m integers. I + 1 th row and j represents the number of times j-th bit of the i-maintenance technicians need to use vehicle T.

Output formats:

The minimum average waiting time, accurate answers to two decimal places.

Input Output Sample
Input Sample # 1:

2 2
3 2
1 4

Output Sample # 1:

1.50

Explanation

(2<=M<=9,1<=N<=60), (1<=T<=1000)

analysis

After reading the title, much like we found a bipartite graph matching problem, so it can be used to write a stream network.

Found that time the title is equivalent to the cost, you can write the cost of flow.

I wanted to: 1. establish super level source point s Super source s , even the sides of all the car, a capacity, a cost of 0,
2. Establish super level exchange point t Super Meeting Point t , even with all the master side, a capacity, a cost of 0,
3. Then all cars and all connected master side in accordance with the cost matrix.

This seems to be the (right)?

Ah, after the C h d Y Chdy discussed, he awoke me to observe the data range, there must be a person to repair a lot of cars, these cars customers need to be in front of people restrictions, that is to say, customers of each repair are subject to the front of each person's limitations , which is split into a required number of master n m n*m a, to meet the needs of each moment.

So the above chart only need to build a third step in detail on the line, the effect is the same.

Specific look at the code comments.

code

/*
	Problem:LUOGU 2053
	Author:hsmshmily
	Date: 2019.6.17 06:38
	State: Solved
	Memo:最小费用最大流
*/

#include<bits/stdc++.h>
using namespace std;
const int maxn=1010,maxm=1e5+10,inf=0x3f3f3f3f;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)s
{
	x=0;
	T f=1, ch=getchar();
	while (!isdigit(ch) && ch^'-') ch=getchar();
	if (ch=='-') f=-1, ch=getchar();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
	x*=f;
}

template<typename T>inline void write(T x)
{
	if (!x) { putchar('0'); return ; }
	if (x<0) putchar('-'), x=-x;
	T num=0, ch[20];
	while (x) ch[++num]=x%10+48, x/=10;
	while (num) putchar(ch[num--]);
}

int ver[maxm<<1],edge[maxm<<1],Next[maxm<<1],cost[maxm<<1],head[maxn],len=1;
inline void add(int x,int y,int z,int c)
{
	ver[++len]=y,edge[len]=z,cost[len]=c,Next[len]=head[x],head[x]=len;
	ver[++len]=x,edge[len]=0,cost[len]=-c,Next[len]=head[y],head[y]=len;
}

int s,t;
int dist[maxn],incf[maxn],pre[maxn];
bool vis[maxn];
inline bool spfa()
{
	memset(dist,0x3f,sizeof(dist));
	memset(vis,0,sizeof(vis));
	queue<int>q;q.push(s);
	dist[s]=0,vis[s]=1,incf[s]=1<<30;
	while (!q.empty())
	{
		int x=q.front();
		q.pop();
		vis[x]=0;
		for (int i=head[x]; i; i=Next[i])
		{
			if (!edge[i]) continue;
			int y=ver[i];
			if (dist[y]>dist[x]+cost[i])
			{
				dist[y]=dist[x]+cost[i];
				incf[y]=min(incf[x],edge[i]);
				pre[y]=i;
				if (!vis[y]) q.push(y),vis[y]=1;
			}
		}
	}
	if (dist[t]==inf) return false;
	else return true;
}

long long maxflow,ans;
inline void update()
{
	int x=t;
	while (x!=s)
	{
		int i=pre[x];
		edge[i]-=incf[t];
		edge[i^1]+=incf[t];
		x=ver[i^1];
	}
	maxflow+=incf[t];
	ans+=dist[t]*incf[t];
}

int main()
{
	int m,n;//1~n 为车数,n+1~n+n*m 为师傅数
	read(m);read(n);
	for (int i=1; i<=n; ++i)
		for (int j=1,c; j<=m; ++j)
		{
			read(c);
			for (int k=1; k<=n; ++k) add(i,j*n+k,1,c*k);//add(i,n+hash(j,k),1,c*k);
		}//将m位师傅拆成n*m个点,第(i-1)*n+j个点表示的是在修第j辆车的第i位师傅

	s=0,t=n+n*m+1;
	for (int i=1; i<=n; ++i) add(s,i,1,0);//将源点与车分别连起来
	for (int i=n+1; i<=n+n*m; ++i) add(i,t,1,0);//将师傅分别与汇点连起来
	while (spfa()) update();
	printf("%.2f\n",ans/(double)n);
	return 0;
}

Guess you like

Origin blog.csdn.net/huashuimu2003/article/details/92535635