BZOJ 2879: [Noi2012] Food Festival Minimum Cost Maximum + Dynamic even side

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

BZOJ 2879
LUOGU 2050
Description

CZ City to welcome the students across the country, specially organized a grand food festival. As an early adopters of foodies, small M would not want to miss the party. He soon tasted the food festival all the food. However, early adopters desire is insatiable. Despite all the dishes are delicious, chef cook very fast, small M still feel the table is not already on the table people food is an intolerable thing. So the little M began to study the problem of cooking sequence, ie the order to arrange a cooking makes the students of the shortest waiting time. Small M found that food festival a total of n different dishes. Every meal, every student can choose a dish of them. A total of m chefs to make these dishes. When all the students end point of the meal, dishes production tasks will be assigned to each chef. Then each chef will also start the cooking. The chefs will be made in accordance with the requirements of the order, and you can only make one person. Additionally, small pieces of M also found another interesting thing: Although this would m cooks all prepared vegetables n products, but for the same dishes, chef different production time is not necessarily the same. He will dishes with 1, 2, ..., n sequentially numbered, chef 1, 2, ..., m are sequentially numbered, the j-th time of the chef i vegetables products referred to as ti, j. Small M said: waiting time for each student for all chefs cook from the start, to their own share of the total length of time until the completion of dishes. In other words, if a student point of the dish is a chef of the k-course, he's waiting time is the chef of time before the course and k. The total waiting time is the waiting time for all students and. Now, to find a small M ordering information for all students: students have a point pi of the i vegetables products (i = 1, 2, ..., n). He wanted to know the smallest total waiting time is.

Input

The first line input file contains two positive integers n and m, the number represents the number of kinds of dishes and cooks. Line 2 contains the positive integer n, where is the i-th pi, i represents the number of points vegetables products. Then there are n rows, each row containing a non-negative integer m, the j-th row of the n number of the i-th row is Ti, j, j-th chef i-th time needed to grow vegetables products. By two numbers separated by a space between each line of the input file adjacent end of the line are no extra spaces.

Output

Output only one row contains an integer, the minimum value of the total waiting time.

Sample Input

3 2
3 1 1
5 7
3 6
8 9

Sample Output

47
[DESCRIPTION] Sample
Cook 1 1 the first part 2 dishes, and then 2 parts prepared dishes 1. This waiting time of 3 ± 3 students were 3,3 + 8,3 + 5 = 5 + 5 = 13.
1 the first part 2 cook dishes 1, and then make a 3 parts dishes. This waiting time two courses are two students 7,7 + 9 = 16.
The total latency of 3 + 8 + 7 + 13 + 16 = 47.
Although the dishes 1 and 3 dishes made by the chef 1 faster if these dishes made by chef 1, but the total waiting time is longer. If the practice described above, 1 part of dishes 1 and 3 was adjusted to 1 parts cook dishes 2 production, so that cooks 2 is not idle, the total waiting time is shorter.
Can attest, there is no better meal plan.
[Data size] and agreed
to 100% of the data, n <= 40, m < = 100, p <= 800, ti, j <= 1000 ( where p = Σpi, i.e., the total number of students ordering).
Each set of n data, m and p values are as follows:
Test point number NMP
. 1. 5 m = n = p = 10. 5
2 40 m = n = p. 1 = 400
. 3 40 n = m = 2 p = 300
. 4 n = 40 m = 40 P = 40
. 5 n-=. 5 m = 40 P = 100
. 6 n-= 10 m = 50 P = 200 is
. 7 n-= 20 is m = 60 P = 400
. 8 n-= 40 m = 80 P = 600
. 9 n-= 40 m = 100 p = 800
10 n = 40 m = 100 p = 800

analysis

When just read the title of this question and think like car repair, but did not go into the heart, re-thinking management of the times, knocking code, like repairing a car and knocked almost, but examples are a few, ah, this is very embarrassing.

After the discovery totals n m p n * m * p a, but also ran p p times s p f a spfa , this will be given overtime, do not know how to optimize ah, just rolled his solution to a problem, even the original dynamic to the edge ah.

This is the use of s p f a spfa run on the sparse graph will be faster in principle, the current point in time can not reach the first matter, at this point in time to go to these nodes added to this picture, this way, complexity you can get a guarantee.

Of course, the specific method see c O d e code in a comment best friends.

code

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+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)
{
	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[maxn<<1],edge[maxn<<1],Next[maxn<<1],cost[maxn<<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;
int c[41][101],p[maxn],num;
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];
	//动态开点,若是同修车那样建图,需要跑p遍spfa,吃不消啊
	x=ver[pre[t]^1];//某位厨师在做倒数第x道菜后
	p[++num]=p[x];//同时记录厨师拆出的点所对应的厨师
	add(num,t,1,0);//厨师拆出的点也要和汇点相连,代表在这一时刻只能做这一种菜
    for (int i=head[x]; i; i=Next[i])
    {
    	int y=ver[i],z=cost[i^1];
    	if (y==t) continue;
    	z+=c[y][p[x]];
    	add(y,num,1,z);//再把他做倒数第x+1道菜的边加上
	}
}

int main()
{
	int n,m;read(n);read(m);//1~n为菜品,n+1~n+m为厨师

	s=0,num=t=n+m+1;
	for (int i=1,x; i<=n; ++i) read(x),add(s,i,x,0);//限制每种菜品被制作的次数
	for (int i=1; i<=n; ++i)
		for (int j=1; j<=m; ++j) read(c[i][j]),add(i,n+j,1,c[i][j]);//菜品和相应厨师连边,代价为所花时间
	for (int i=1; i<=m; ++i) add(i+n,t,1,0),p[n+i]=i;//每一个人在同一时间只能做一种菜

	while (spfa()) update();
	write(ans);
	return 0;
}

Guess you like

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