【最大流】ECNA 2015 F Transportation Delegation (Codeforces GYM 100825)

题目链接:

  http://codeforces.com/gym/100825

题目大意:

  N(N<=600)个点,每个点有个名字Si,R(R<=200)个生产商在R个点上,F(F<=200)个工厂在F个点上,不会有一个点既有生产商又有工厂

  有T(T<=1000)个公司,每个公司能够到达Ci个点,并且一个只能运输一个生产商的货物。比如生产商1给工厂1运输货物需要用到公司1,那么其余生产商就不能用公司1

  一个工厂需要任意一个生产商供应货物,求最多能够给多少个工厂供应货物。

题目思路:

  【最大流】

  因为一个公司只能被一个生产商使用,所以将每个公司拆点为A和A两个点,A到A中间流量为1

  A公司能够到达的所有点向A连一条流量为1的边,A到所能能到达的点连一条流量为1的边。

  设置超级源S和超级汇T,超级源S到每一个生产商连一条流量为1的边,每个工厂到超级汇T连一条流量为1的边。

  跑一遍最大流即可。

 




//
//by coolxxx
//#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<iomanip>
#include<map>
#include<stack>
#include<queue>
#include<set>
#include<bitset>
#include<memory.h>
#include<time.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//#include<stdbool.h>
#include<math.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(a) ((a)>0?(a):(-(a)))
#define lowbit(a) (a&(-a))
#define sqr(a) ((a)*(a))
#define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define eps (1e-10)
#define J 10000
#define mod 1000000007
#define MAX 0x7f7f7f7f
#define PI 3.14159265358979323
#pragma comment(linker,"/STACK:1024000000,1024000000")
#define N 3004
#define M 5000004
using namespace std;
typedef long long LL;
double anss;
LL aans;
int cas,cass;
int n,m,lll,ans;
int S,T,nn,m1,m2;
int d[N],vd[N],last[N];
struct xxx
{
	int next,to,q;
}a[M];
int ma[N][N];
string ss;
string s[N];
map<string,int>id;
void add(int x,int y,int z)
{
	a[++lll].to=y;
	a[lll].q=z;
	a[lll].next=last[x];
	last[x]=lll;
}
int sap(int u,int f)
{
	int i,v,tt,asp=0,mix=nn-1;
	if(u==T)return f;
	for(i=last[u];i!=0;i=a[i].next)
	{
		v=a[i].to;
		if(a[i].q>0)
		{
			if(d[u]==d[v]+1)
			{
				tt=sap(v,min(f-asp,a[i].q));
				asp+=tt;
				a[i].q-=tt;
				a[i^1].q+=tt;
				if(asp==f || d[S]==nn)
					return asp;
			}
			mix=min(mix,d[v]);
		}
	}
	if(asp!=0)return asp;
	if(!--vd[d[u]])d[S]=nn;
	else vd[d[u]=mix+1]++;
	return asp;
}
int main()
{
	#ifndef ONLINE_JUDGE
//	freopen("1.txt","r",stdin);
//	freopen("2.txt","w",stdout);
	#endif
	int i,j,k;
	int x,y,z,f;
//	init();
//	for(scanf("%d",&cass);cass;cass--)
//	for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
//	while(~scanf("%s",s))
	while(~scanf("%d",&n))
	{
		lll=1;
		scanf("%d%d%d",&m1,&m2,&m);
		S=n+m+m+1,T=n+m+m+2;
		for(i=1;i<=m1;i++)
		{
			cin>>ss;
			if(id.find(ss)==id.end())
				id[ss]=++cass;
			j=id[ss];
			add(S,j,1);
			add(j,S,0);
		}
		for(i=1;i<=m2;i++)
		{
			cin>>ss;
			if(id.find(ss)==id.end())
				id[ss]=++cass;
			j=id[ss];
			add(j,T,1);
			add(T,j,0);
		}
		for(i=1;i<=m;i++)
		{
			add(n+i+i-1,n+i+i,1),add(n+i+i,n+i+i-1,0);
			scanf("%d",&cas);
			for(j=1;j<=cas;j++)
			{
				cin>>s[j];
				if(id.find(s[j])==id.end())
					id[s[j]]=++cass;
				k=id[s[j]];
				add(k,n+i+i-1,1),add(n+i+i-1,k,0);
				add(n+i+i,k,1),add(k,n+i+i,0);
			}
		}
		nn=T;
		vd[0]=nn;
		while(d[S]<nn)
		{
			f=sap(S,MAX);
			ans+=f;
		}
		printf("%d\n",ans);
		
		cass=0;ans=0;
		mem(last,0);mem(d,0);mem(vd,0);
		id.clear();
	}
	return 0;
}
/*
//

//
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值