【USACO07OPEN】吃饭Dining(最大流)

版权声明:虽然我很菜,不过转载请标明出处。 https://blog.csdn.net/Patrickpwq/article/details/86649685

将超级源点先与所有食物相连,容量为1(这代表每种食物主人只能有一个),

饮料和超级汇点相连,容量也为1(这代表饮料的主人只有一个),

随后食物与对应的牛相连,容量也为1(这代表每种食物量为1,选完就没有了),以及牛与饮料连1(这代表每种饮料量为1,选完就没有了),

不过注意到隐藏的限制条件,流入牛的流量有可能大于1,流入饮料的流量也可能大于1,这代表这头牛选了多个食物/饮料,每只牛只能选择一种食物和饮料,这样的话,我们采用拆点的方式,将牛拆为入点和出点,连1的边,就保证了流入/流出的流量最多为1

#include<bits/stdc++.h>
const int N=405;
const int M=100005;
const int INF=0x3f3f3f3f;
using namespace std;
int n,f,d,s,t;
struct Edge
{
	int to,next,cap;
}edge[2*M];
int first[N],tot=1;
inline void addedge(int x,int y,int z)
{
	tot++;
	edge[tot].to=y; edge[tot].next=first[x]; edge[tot].cap=z; first[x]=tot;
}
int step[N],cur[N];
bool bfs()
{
	memset(step,-1,sizeof(step));
	queue<int> q;
	q.push(s); step[s]=1;
	while(!q.empty())
	{
		int now=q.front(); q.pop();
		for(int u=first[now];u;u=edge[u].next)
		{
			int vis=edge[u].to;
			if(step[vis]==-1&&edge[u].cap>0)
			{
				step[vis]=step[now]+1;
				q.push(vis);
				if(vis==t)	return 1;
			}
		}
	}
	return 0;
}
int dfs(int now,int f)
{
	if(!f||now==t)	return f;
	int out=0;
	for(int &u=cur[now];u;u=edge[u].next)
	{
		int vis=edge[u].to;
		if(edge[u].cap&&step[vis]==step[now]+1)
		{
			int w=dfs(vis,min(f,edge[u].cap));
			if(w==0)	continue;
			out+=w; f-=w; 
			edge[u].cap-=w; edge[u^1].cap+=w;
			if(f==0)	break;
		}
	}
	return out;
	
}
void Maxflow()
{
	int ans=0;
	while(bfs())
	{
		for(int i=1;i<=t;i++)	cur[i]=first[i];
		ans+=dfs(s,INF);
	}
	cout<<ans<<endl;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);	cout.tie(NULL);
	cin>>n>>f>>d;
	s=1,t=1+f+n+n+d+1;
	for(int i=2;i<=f+1;i++)
	{
		addedge(s,i,1);
		addedge(i,s,0);
	}
	for(int i=1+f+n+n+1;i<=1+f+n+n+d;i++)
	{
		addedge(i,t,1);
		addedge(t,i,0);
	}
	for(int i=1+f+1;i<=1+f+n;i++)
	{
		addedge(i,i+n,1);
		addedge(i+n,i,0);
	}
	for(int i=1,fi,di,x;i<=n;i++)
	{
		cin>>fi>>di;
		for(int j=1;j<=fi;j++)
		{
			cin>>x;
			addedge(x+1,1+f+i,1);
			addedge(1+f+i,x+1,0);
		}
		for(int j=1;j<=di;j++)
		{
			cin>>x;
			addedge(1+f+n+i,1+f+n+n+x,1);
			addedge(1+f+n+n+x,1+f+n+i,0);
		}
	}
	Maxflow();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Patrickpwq/article/details/86649685