• [BZOJ1280]Emmy卖猪pigs


    题目大意:
    Emmy在一个养猪场工作。这个养猪场有M个锁着的猪圈,但Emmy并没有钥匙。顾客会到养猪场来买猪,一个接着一个。每一位顾客都会有一些猪圈的钥匙,他们会将这些猪圈打开并买走固定数目的猪。 所有顾客有的钥匙和他们需要买猪的数量在事先都告诉了Emmy,于是Emmy要订一个计划,使得卖出去的猪最多。 买卖的过程是这样的:一个顾客前来,并打开所有他可以打开的猪圈。然后Emmy从这些猪圈里牵出固定数目的猪卖给顾客(最多只能和顾客需要数相等),并可以重新安排这些开着的猪圈中的猪。 每个猪圈可以存放任意数目的猪。 写一个程序,使得Emmy能够卖出去尽可能多的猪。
    解题思路:
    最大流。
    从源向猪圈连容量为初始猪的数量的边。
    对于每一个顾客可以开的猪圈,若该猪圈被之前的顾客打开过,则从最后打开过这个猪圈的顾客向这个顾客连容量为inf的边,否则从这个猪圈向该顾客连容量inf的边。
    对于每个顾客,向汇点连容量为inf的边。
    为什么这么连边呢?
    首先,第一个打开猪圈的顾客拿猪是没问题的。
    其次,若一个猪圈已经被一个顾客开了,那么这个顾客可以得到原来那个顾客打开的其他猪圈的猪(可以通过交换得到),更早打开的也可以通过顾客链传递过来。

    C++ Code:

    #include<cstdio>
    #include<cctype>
    #include<cctype>
    #include<cstring>
    #include<queue>
    const int S=0,T=2330,inf=0x3f3f3f3f;
    #include<iostream>
    using std::cin;
    using std::cout;
    using std::endl;
    int n,m,head[2333],cnt=1,pig[2333]={0},level[2333],iter[2333];
    struct edge{
    	int to,nxt,cap;
    }e[400005];
    inline void addedge(int u,int v,int t){
    	e[++cnt]=(edge){v,head[u],t};
    	head[u]=cnt;
    	e[++cnt]=(edge){u,head[v],0};
    	head[v]=cnt;
    }
    std::queue<int>q;
    void bfs(){
    	level[S]=1;
    	for(q.push(S);!q.empty();){
    		int u=q.front();
    		q.pop();
    		for(int i=head[u];~i;i=e[i].nxt)
    		if(e[i].cap&&!~level[e[i].to]){
    			level[e[i].to]=level[u]+1;
    			q.push(e[i].to);
    		}
    	}
    }
    inline int min(int a,int b){return a<b?a:b;}
    int dfs(int u,int f){
    	if(!f||u==T)return f;
    	for(int& i=iter[u];~i;i=e[i].nxt)
    	if(e[i].cap&&level[e[i].to]>level[u]){
    		int d=dfs(e[i].to,min(f,e[i].cap));
    		if(d){
    			e[i].cap-=d;
    			e[i^1].cap+=d;
    			return d;
    		}else level[e[i].to]=-1;
    	}
    	return 0;
    }
    int dinic(){
    	for(int flow=0,f;;){
    		memset(level,-1,sizeof pig);
    		if(bfs(),!~level[T])return flow;
    		memcpy(iter,head,sizeof pig);
    		while(f=dfs(S,inf))flow+=f;
    	}
    }
    int main(){
    	cin>>n>>m;
    	memset(head,-1,sizeof head);
    	for(int i=1,p;i<=n;++i){
    		cin>>p;
    		addedge(S,i,p);
    	}
    	for(int i=1,p;i<=m;++i){
    		const int id=n+i;
    		cin>>p;
    		for(int k;p--;){
    			cin>>k;
    			if(pig[k])addedge(pig[k],id,inf);else
    			addedge(k,id,inf);
    			pig[k]=id;
    		}
    		cin>>p;
    		addedge(id,T,p);
    	}
    	cout<<dinic()<<endl;
    	return 0;
    }
    
  • 相关阅读:
    A. Difference Row
    B. Fixed Points
    命运
    Climbing Worm
    大学感想
    Constructing Roads
    lintcode605- Sequence Reconstruction- medium- airbnb google
    lintcode616- Course Schedule II- medium
    lintcode615- Course Schedule- medium
    lintcode127- Topological Sorting- medium
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9288496.html
Copyright © 2020-2023  润新知