BZOJ 1061 [Noi2008]志愿者招募

题解:

线性规划转网络流

再次提醒自己别把变量的范围搞混了

 

 

然后用等式代表点,变量代表边,常量代表最终流向t还是由s流入,跑最小费用最大流

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=1009;
const int maxm=10009;
const int oo=1000000000;

int n,m;
int be[maxm],en[maxm],co[maxm];

struct Edge{
	int from,to,cap,flow,cost;
};
vector<int>G[maxn];
vector<Edge>edges;
void Addedge(int x,int y,int z,int w){
//	cout<<x<<' '<<y<<endl;
	Edge e;
	e.from=x;e.to=y;e.cap=z;e.flow=0;e.cost=w;
	edges.push_back(e);
	e.from=y;e.to=x;e.cap=0;e.flow=0;e.cost=-w;
	edges.push_back(e);
	int c=edges.size();
	G[x].push_back(c-2);
	G[y].push_back(c-1);
}

int s,t,totn;
int inq[maxn];
int d[maxn];
int pre[maxn];
queue<int>q;
int Spfa(int &nowflow,int &nowcost){
	for(int i=1;i<=totn;++i){
		inq[i]=0;d[i]=oo;
	}
	d[s]=0;inq[s]=1;q.push(s);
	while(!q.empty()){
		int x=q.front();q.pop();inq[x]=0;
		for(int i=0;i<G[x].size();++i){
			Edge e=edges[G[x][i]];
			if((e.cap>e.flow)&&(d[x]+e.cost<d[e.to])){
				d[e.to]=d[x]+e.cost;
				pre[e.to]=G[x][i];
				if(!inq[e.to]){
					inq[e.to]=1;
					q.push(e.to);
				}
			}
		}
	}
	if(d[t]==oo)return 0;
	
	int x=t,f=oo;
	while(x!=s){
		Edge e=edges[pre[x]];
		f=min(f,e.cap-e.flow);
		x=e.from;
	}
	nowflow+=f;nowcost+=f*d[t];
	x=t;
	while(x!=s){
		edges[pre[x]].flow+=f;
		edges[pre[x]^1].flow-=f;
		x=edges[pre[x]].from;
	}
	return 1;
}

int Mincost(){
	int flow=0,cost=0;
	while(Spfa(flow,cost)){
	}
	return cost;
}

int a[maxn][maxm];

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)scanf("%d",&a[i][m+1]);
	for(int i=1;i<=m;++i)scanf("%d%d%d",&be[i],&en[i],&co[i]);
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j){
			if((be[j]<=i)&&(en[j]>=i))a[i][j]=1;
		}
	}
//	for(int i=1;i<=n+1;++i){
//		for(int j=1;j<=m+1;++j){
//			cout<<a[i][j]<<' ';
//		}
//		cout<<endl;
//	}
//	cout<<"eating shit"<<endl;
	for(int i=n+1;i>=1;--i){
		for(int j=1;j<=m+1;++j){
			a[i][j]=a[i][j]-a[i-1][j];
		}
	}
//	for(int i=1;i<=n+1;++i){
//		for(int j=1;j<=m+1;++j){
//			cout<<a[i][j]<<' ';
//		}
//		cout<<endl;
//	}
	totn=n+1;s=++totn;t=++totn;
	for(int i=1;i<=n+1;++i){
		if(i>1)Addedge(i,i-1,oo,0);
		if(a[i][m+1]>0)Addedge(s,i,a[i][m+1],0);
		else Addedge(i,t,-a[i][m+1],0);
	}
	for(int j=1;j<=m;++j){
		int p1=0,p2=0;
		for(int i=1;i<=n+1;++i){
			if(a[i][j]==1){
				p1=i;break;
			}
		}
		for(int i=n+1;i>=1;--i){
			if(a[i][j]==-1){
				p2=i;break;
			}
		}
		Addedge(p1,p2,oo,co[j]);
	}
	
	cout<<Mincost()<<endl;
	return 0;
}

  

posted @ 2018-03-14 11:24  ws_zzy  阅读(122)  评论(0编辑  收藏  举报