zoukankan      html  css  js  c++  java
  • [POJ1149][SPOJ4063]PIGS(最大流)

    [POJ1149][SPOJ4063]PIGS(最大流)

    题面

    分析

    很妙的网络流建图套路。

    注意到我们只能交换客户打开过的猪圈里的猪。那么相当于可以通过顾客来中转猪。体现到建图上就是:
    我们把每一个顾客看成一个点。对于每个猪圈,从原点向打开它的第一个顾客连边,容量为初始猪数量(a_i),表示最多可以提供的量.每个顾客向汇点连容量为需求量(b_j)的边。对于同一个猪圈的所有顾客,我们将它按时间顺序连起来,容量为(+infin)。比如从顾客(j)向顾客(j+1)连边,就可以表示顾客(j)打开猪圈(i)买完猪后,将(i)中的猪换到(j+1)打开的猪圈中。

    网络最大流即为答案

    代码

    //https://www.luogu.com.cn/problem/SP4063
    #include<iostream>
    #include<cstdio>
    #include<cstring> 
    #include<vector>
    #include<queue> 
    #define INF 0x3f3f3f3f 
    #define maxn 10000
    #define maxm 100000
    using namespace std;
    int n,m;
    int a[maxn+5],b[maxn+5];
    vector<int>p[maxn+5];
    
    struct edge{
    	int from;
    	int to;
    	int next;
    	int flow;
    }E[maxm*2+5];
    int sz=1;
    int head[maxn+5];
    void add_edge(int u,int v,int w){
    //	printf("%d->%d %d
    ",u,v,w);
    	sz++;
    	E[sz].from=u;
    	E[sz].to=v;
    	E[sz].next=head[u];
    	E[sz].flow=w;
    	head[u]=sz;
    	sz++;
    	E[sz].from=v;
    	E[sz].to=u;
    	E[sz].next=head[v];
    	E[sz].flow=0;
    	head[v]=sz;
    }
    int deep[maxn+5];
    bool bfs(int s,int t){
    	for(int i=s;i<=t;i++) deep[i]=0;
    	queue<int>q;
    	q.push(s);
    	deep[s]=1;
    	while(!q.empty()){
    		int x=q.front();
    		q.pop();
    		for(int i=head[x];i;i=E[i].next){
    			int y=E[i].to; 
    			if(E[i].flow&&!deep[y]){
    				deep[y]=deep[x]+1;
    				q.push(y);
    			}
    		}
    	}
    	return deep[t]>0;
    } 
    int dfs(int x,int t,int minf){
    	if(x==t) return minf;
    	int rest=minf,k;
    	for(int i=head[x];i;i=E[i].next){
    		int y=E[i].to;
    		if(E[i].flow&&deep[y]==deep[x]+1){
    			k=dfs(y,t,min(rest,E[i].flow));
    			E[i].flow-=k;
    			E[i^1].flow+=k;
    			rest-=k; 
    			if(k==0) deep[y]=0;
    			if(rest==0) break;
    		}
    	}
    	return minf-rest;
    }
    int dinic(int s,int t){
    	int ans=0,now=0;
    	while(bfs(s,t)){
    		while((now=dfs(s,t,INF))) ans+=now;
    	}
    	return ans;
    } 
     
    int main(){
    	scanf("%d %d",&m,&n);
    	for(int i=1;i<=m;i++) scanf("%d",&a[i]);
    	for(int i=1;i<=n;i++){
    		int k,x;
    		scanf("%d",&k);
    		for(int j=1;j<=k;j++){
    			scanf("%d",&x);
    			p[x].push_back(i);
    		}
    		scanf("%d",&b[i]);
    	}
    	int s=0,t=n+1;
    	for(int i=1;i<=m;i++){
    		for(int j=0;j<(int)p[i].size();j++){
    			if(j==0) add_edge(s,p[i][j],a[i]);
    			else add_edge(p[i][j-1],p[i][j],INF);
    		}
    	}
    	for(int i=1;i<=n;i++) add_edge(i,t,b[i]);
    	printf("%d
    ",dinic(s,t));
    }
    
  • 相关阅读:
    适配不同屏幕的宏
    phpstrom 10 激活
    php三维数组去重
    Ajax总结
    Node.js中处理异步编程(使用回调处理一次性事件,使用事件监听器处理重复性事件)
    JavaScript中函数对象的call()和apply()方法的总结
    jQuery中prop()方法和attr()方法可能遇到的问题小结
    Node.js中url的parse、format、resolve方法详解
    处理跨域方式
    JS获取网页窗口大小、浏览器窗口大小、页面元素位置
  • 原文地址:https://www.cnblogs.com/birchtree/p/12594468.html
Copyright © 2011-2022 走看看