现在的位置: 首页 > 综合 > 正文

poj 3228 Gold Transportation

2013年08月25日 ⁄ 综合 ⁄ 共 2083字 ⁄ 字号 评论关闭

我用的二分边长+网络流,这题也可以用枚举边长+并查集来做

对于每个有金矿的点,源点向其连一条容量为金矿数的边,对于每个仓库,向汇点连一条容量为仓库储存量的边,然后对于所有边长不大于当前枚举的值的边,连双向的容量为无穷的边

如果满流,则该枚举的边长可行,继续缩小,否则,枚举更大的边长

边长去重写错了,wa了几次=.=

代码:

#include<iostream>
#include<memory.h>
#include<string>
#include<cstdio>
#include<algorithm>
#include<math.h>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#include<ctime>
using namespace std;
const int MAX=1005;
const int inf=1<<30;
struct node 
{
	int v,c,next;
}g[MAX*100];
struct Edge 
{
	int u,v,w;
}E[MAX*MAX];
int adj[MAX],num[MAX],pre[MAX],cur[MAX],dis[MAX],e,n,m,vn,s,t;
int pos[MAX*MAX],mine[MAX],store[MAX],sum,tot;
void add(int u,int v,int c)
{
	g[e].v=v; g[e].c=c; g[e].next=adj[u]; adj[u]=e++;
	g[e].v=u; g[e].c=0; g[e].next=adj[v]; adj[v]=e++;
	//cout<<u<<" "<<v<<" "<<c<<endl;
}
int sap()
{
	int i,u,v,flag,flow=0,aug=inf;
	for(i=0;i<=vn;i++)
	{
		cur[i]=adj[i];
		dis[i]=num[i]=0;
	}
	num[0]=vn; 
	pre[s]=u=s;
	while(dis[s]<vn)
	{
		flag=0;
		for(i=cur[u];i!=-1;i=g[i].next)
		{
			v=g[i].v;
			if(g[i].c&&dis[u]==dis[v]+1)
			{
				flag=1;
				cur[u]=i;
				pre[v]=u;
				aug=min(aug,g[i].c);
				u=v;
				if(u==t)
				{
					flow+=aug;
					while(u!=s)
					{
						u=pre[u];
						g[cur[u]].c-=aug;
						g[cur[u]^1].c+=aug;
					}
					aug=inf;
				}
				break;
			}
		}
		if(flag)
			continue;
		if(--num[dis[u]]==0)
			break;
		for(dis[u]=vn,i=adj[u];i!=-1;i=g[i].next)
		{
			v=g[i].v;
			if(g[i].c&&dis[v]<dis[u])
			{
				cur[u]=i; dis[u]=dis[v];
			}
		}
		dis[u]++;
		num[dis[u]]++;
		u=pre[u];
	}
	return flow;
}
bool check(int x)
{
	int i;
	memset(adj,-1,sizeof(adj));
	e=0; s=0; t=n+1; vn=t+1;
	for(i=1;i<=n;i++)
	{
		if(mine[i])
			add(s,i,mine[i]);
		if(store[i])
			add(i,t,store[i]);
	}
	for(i=0;i<m;i++)
	{
		if(E[i].w<=x)
		{
			add(E[i].u,E[i].v,inf);
			add(E[i].v,E[i].u,inf);
		}
	}
	return sap()==sum;
}
void solve(int r)
{
	int i,l=0,mid,ans=-1;
	while(l<=r)
	{
		mid=(l+r)>>1;
		if(check(pos[mid]))
		{
			ans=pos[mid];
			r=mid-1;
		}
		else
			l=mid+1;
	}
	if(ans==-1)
		puts("No Solution");
	else
		printf("%d\n",ans);
}
int main()
{
	int i,j,k;
	while(scanf("%d",&n)!=EOF)
	{
		if(n==0)
			break;
		sum=0;
		tot=0;
		for(i=1;i<=n;i++)
		{
			scanf("%d",&mine[i]);
			sum+=mine[i];
		}
		for(i=1;i<=n;i++)
		{
			scanf("%d",&store[i]);
			tot+=store[i];
		}
		scanf("%d",&m);
		j=0;
		for(i=0;i<m;i++)
		{
			scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].w);
			pos[j++]=E[i].w;
		}
		//pos[j++]=0;
		if(tot<sum)
		{
			puts("No Solution");
			continue;
		}
		sort(pos,pos+j);
		k=0;
		for(i=0;i<j;i++)
		{
			if(i==0||pos[i]!=pos[i-1])
				pos[k++]=pos[i];
		}
		solve(k);
	}
	return 0;
}

抱歉!评论已关闭.