• bzoj 3280: 小R的烦恼 费用流


    题目:

    Description

    小R最近遇上了大麻烦,他的程序设计挂科了。于是他只好找程设老师求情。善良的程设老师答应不挂他,但是要求小R帮助他一起解决一个难题。
    问题是这样的,程设老师最近要进行一项邪恶的实验来证明P=NP,这个实验一共持续n天,第i天需要a[i]个研究生来给他搬砖。研究生毕竟也是人,所以雇佣研究生是需要钱的,机智的程设老师已经联系好了m所大学,第j所大学共有l[j]个研究生,同时雇佣这所大学的一个研究生需要p[j]元钱。
    本来程设老师满心欢喜的以为,这样捡最便宜的max{a[i]}个研究生雇来,就可以完成实验;结果没想到,由于他要求硕士生们每天工作25个小时不许吃饭睡觉上厕所喝水说话咳嗽打喷嚏呼吸空气,因此一天下来给他搬砖的所有研究生都会进入濒死状态。濒死状态的研究生,毫无疑问,就不能再进行工作了。但是机智的老师早早联系好了k家医院,第i家医院医治一个濒死的研究生需要d[i]天,并且需要q[i]元钱。
    现在,程设老师想要知道,最少花多少钱,能够在这n天中满足每天的需要呢?若无法满足,则请输出”impossible”。注意,由于程设老师良心大大的坏,所以他是可以不把濒死的研究生送去医院的!

    题解:

    但愿我将来能不会遇到这种程设老师

    这道题不就是餐巾(网络流24题)吗...

    建模如下:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(int &x){
    	x=0;char ch;bool flag = false;
    	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    const int maxn = 40010;
    const int maxnode = 40010;
    const int inf = 0x3f3f3f3f;
    struct Edge{
    	int to,next,cap,cost;
    }G[maxnode<<1];
    int head[maxnode],cnt=1;
    void add(int u,int v,int c,int d){
    	G[++cnt].to = v;
    	G[cnt].next = head[u];
    	head[u] = cnt;
    	G[cnt].cap = c;
    	G[cnt].cost = d;
    }
    inline void insert(int u,int v,int c,int d){
    	add(u,v,c,d);add(v,u,0,-d);
    }
    #define v G[i].to
    const int lim = maxnode<<1;
    int dis[maxnode],flow[maxnode],p[maxnode],q[lim+10];
    int S,T,l,r,ans,tot_flow;bool inq[maxnode];
    inline bool spfa(){
    	memset(dis,0x3f,sizeof dis);
    	inq[S] = true;dis[S] = 0;
    	flow[S] = inf;l = 0;r = -1;
    	q[++r] = S;
    	while(l <= r){
    		int u = q[l % lim];++l;
    		for(int i = head[u];i;i=G[i].next){
    			if(dis[v] > dis[u] + G[i].cost && G[i].cap){
    				dis[v] = dis[u] + G[i].cost;
    				flow[v] =  min(flow[u],G[i].cap);
    				p[v] = i;
    				if(!inq[v]){
    					q[++r % lim] = v;
    					inq[v] = true;
    				}
    			}
    		}inq[u] = false;
    	}if(dis[T] == dis[T+1]) return false;
    	ans += dis[T]*flow[T];
    	tot_flow += flow[T];
    	for(int u = T;u != S;u = G[p[u]^1].to)
    		G[p[u]].cap -= flow[T],G[p[u]^1].cap += flow[T];
    	return true;
    }
    #undef v
    int a[maxn],L[maxn],P[maxn],D[maxn],Q[maxn];
    inline void init(){
    	memset(head,0,sizeof head);
    	cnt = 1;tot_flow = 0;ans = 0;
    }
    inline void work(){
    	init();	
    	int n,m,k;read(n);read(m);read(k);
    	S = maxnode - 5;T = S + 1;
    	for(int i=1;i<=n;++i){
    		read(a[i]);tot_flow -= a[i];
    		insert(i,T,a[i],0);
    		insert(S,i+n,a[i],0);
    		if(i != n) insert(i,i+1,inf,0);
    	}
    	for(int i=1;i<=m;++i){
    		read(L[i]);read(P[i]);
    		insert(S,1,L[i],P[i]);
    	}
    	for(int i=1;i<=k;++i){
    		read(D[i]);read(Q[i]);
    		for(int j=1;j<=n;++j){
    			if(j + D[i] + 1 > n) break;
    			insert(j+n,j+D[i]+1,inf,Q[i]);
    		}
    	}
    	while(spfa());
    	if(tot_flow < 0) puts("impossible");
    	else printf("%d
    ",ans);
    }
    int main(){
    	int T;read(T);
    	for(int i=1;i<=T;++i){
    		printf("Case %d: ",i);
    		work();
    	}
    	getchar();getchar();
    	return 0;
    }
    
  • 相关阅读:
    LibreOJ 6282 数列分块入门 6(在线插入在线查询)
    LibreOJ 6281 数列分块入门 5(分块区间开方区间求和)
    LibreOJ 6280 数列分块入门 4(分块区间加区间求和)
    LibreOJ 6279 数列分块入门 3(分块+排序)
    LibreOJ 6278 数列分块入门 2(分块)
    LibreOJ 6277 数列分块入门 1(分块)
    BZOJ 2301 Problem b(莫比乌斯反演+分块优化)
    MD5Untils加密工具类
    20160418javaweb之 Filter过滤器
    20160417javaweb之servlet监听器
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6568424.html
Copyright © 2020-2023  润新知