有源匯上下界最大流 ZOJ 3229 代碼

//ZOJ - 3229
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 1500;
const int maxm = 400000;
const int INF = 0x3ffffff;
struct Side{
	int to,next,c;
}side[maxm*2];
int node[maxn],top,cnt,start,end;
void add_side(int u,int v,int c){
	side[top]=(Side){v,node[u],c};node[u]=top++;
	side[top]=(Side){u,node[v],0};node[v]=top++;
}
int dis[maxn],gap[maxn];
int get_flow(int u,int flow){
	if(u==end)return flow;
	int ans=0;
	for(int i=node[u];i!=-1;i=side[i].next){
		int v=side[i].to;
		if(dis[u]>dis[v]&&side[i].c){
			int f=get_flow(v,min(side[i].c,flow-ans));
			side[i].c-=f;
			side[i^1].c+=f;
			ans+=f;
			if(ans==flow)return flow;
		}
	}
	if(!(--gap[dis[u]]))dis[start]=cnt+2;
	gap[++dis[u]]++;
	return ans;
}
int low[400][1000],up[400][1000],id[400][1000],c[400];
int d[400],g[1000];
int du[maxn];
int s,e;
int main(){
	int n,m;
	while(~scanf("%d%d",&n,&m)){
		top=0;
		memset(node,-1,sizeof(node));
		memset(du,0,sizeof(du));
		memset(dis,0,sizeof(dis));
		memset(gap,0,sizeof(gap));
		cnt=n+m+4;
		s=n+m;
		e=n+m+1;
		start=n+m+2;
		end=n+m+3;
		for(int i=0;i<m;i++){
			scanf("%d",&g[i]);
			add_side(i,e,INF);
			du[i]-=g[i];
			du[e]+=g[i];
		}
		for(int i=0;i<n;i++){
			int u=m+i;
			scanf("%d%d",&c[i],&d[i]);
			add_side(s,u,d[i]);
			for(int j=0;j<c[i];j++){
				int v;
				scanf("%d%d%d",&v,&low[i][j],&up[i][j]);
				add_side(u,v,up[i][j]-low[i][j]);
				du[v]+=low[i][j];
				du[u]-=low[i][j];
				id[i][j]=top-1;
			}
		}
		int target=0,ans=0;
		add_side(e,s,INF);
		for(int i=0;i<=e;i++){
			if(du[i]>0)target+=du[i];
			if(du[i]>0)add_side(start,i,du[i]);
			else if(du[i]<0)add_side(i,end,-du[i]);
		}
		gap[0]=cnt;
		while(dis[start]<cnt)ans+=get_flow(start,INF);
		if(ans==target){
			memset(gap,0,sizeof(gap));
			memset(dis,0,sizeof(dis));
			dis[start]=dis[end]=cnt;
			cnt-=2;
			node[start]=node[end]=-1;
			start=s;
			end=e;
			gap[0]=cnt;
			ans=0;
			while(dis[start]<cnt)ans+=get_flow(start,INF);
			ans=0;
			for(int i=0;i<n;i++){
				for(int j=0;j<c[i];j++){
					ans+=side[id[i][j]].c+low[i][j];
				}
			}
			printf("%d\n",ans);
			for(int i=0;i<n;i++){
				for(int j=0;j<c[i];j++){
					printf("%d\n",side[id[i][j]].c+low[i][j]);
				}
			}
		}else printf("-1\n");
		printf("\n");
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章