BZOJ 1061: [Noi2008] volunteer recruitment 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

BZOJ 1061
Description

After the successful Olympic bid, boob through unremitting efforts, has finally become director of BOCOG subsidiary HR department. Bubu took office just ran into a problem: the recruitment of a number of short-term volunteers for the upcoming launch of the new Olympic project. After estimating that the project requires N days to complete, with the first day at least i Ai individual. Bubu by understanding that a total of M class volunteers can be recruited. Wherein the i-type Si from the first day to work on Day Ti, Ci recruitment costs per person. New broom sweeps clean, well done to their jobs, boob to exhaust less cost of recruiting enough volunteers, but this is not his specialty! So Bubu found you, I hope you help him design an optimal recruitment programs.

Input

The first line contains two integers N, M, indicating the type and number of days to complete the project can recruit volunteers. The next line contains N non-negative integers, it represents the required minimum number of volunteers per day. The next M rows each line contains three integers Si, Ti, Ci, meanings as described above. For convenience, we can say that the number of each type are an infinite number of volunteers.

Output

Only contains an integer that represents the total cost of the optimal solution of your design.

Sample Input

3 3
2 3 4
1 2 2
2 3 5
3 3 2

Sample Output

14

HINT

1 ≤ N ≤ 1000,1 ≤ M ≤ 10000, the title of the other data involved does not exceed 2 ^ 31-1.

analysis

This question is to write good problem solution.

At first model I have in mind is active sink lower bound of network flow, ah, will not be processed, it stunned an hour.

Afternoon after school to the room, ask the C h d Y Chdy , found built a small drawing skills, really wonderful!

My original idea is to first i i day of the first i + 1 i+1 between the sky and the edge, but certainly better than the first capacity i i needed day large number of volunteers, so a bit uncomfortable.

Then, this little trick is this:
we observe: For convenience, we can say that the number of each type are an infinite number of volunteers.
Ah, we put all the sides to capacity I N F INF Number of volunteers in order to meet the required minimum daily x x , to use I N F x INF-x as their capacity, forced into lower bound upper bound, that we write the most common network flow.

There is also a thinking skills: we will all edges of the capacity vested endpoint his left, so if we want to ensure that the first n n the number of volunteers needed days, we need to build a n + 1 n+1 point, but we must also ensure the capacity and the meeting point of that edge is even I N F INF , so we need to build a exchange point t Meeting Point t , and n + 1 n+1 even capacity I N F INF , The cost of 0 0 edge.

Then the other on the no need to say, it's all routine.

code

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e6+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;
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 n,m;
	read(n);read(m);
	s=0,t=n+m+1;
	for (int i=1,x; i<=n; ++i) read(x),add(i,i+1,inf-x,0);//将下界网络流转化为上届网络流的一个神奇操作
	add(s,1,inf,0),add(n+1,t,inf,0);
	for (int i=1,si,ti,ci; i<=m; ++i) read(si),read(ti),read(ci),add(si,ti+1,inf,ci);
	while (spfa()) update();
	write(ans);
	return 0;
}

Guess you like

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