P2891 [USACO07OPEN]吃饭Dining

P2891 [USACO07OPEN]吃饭Dining

这题就是网络流的一个技巧,学会了就很好做了

以下连边默认是容量为1的。
考虑把牛拆成两个点,中间连容量为1的边,这样就保证了一头牛只会被经过一次(否则它可能享用很多食物)。前面的点(入点)负责连入边,后面的点(出点)负责连出边。从食物向入点连边,出点向饮料连边。另设超级源点s向食物连边,饮料向超级汇点t连边。

样例的图建好大概长这样

看完图应该就很好理解了。
代码特地放了注释。可以把注释符号删掉,看看连了那些边。

#include<bits/stdc++.h>
using namespace std;
const int N=420;
const int inf=1000000007;
int n,f,d,s,t,sum;
struct edge{
	int nxt,val,to;
}e[21000*2];
int head[N],num_edge=1;
void add(int from,int to,int val)
{
	++num_edge;
	e[num_edge].nxt=head[from];
	e[num_edge].to=to;
	e[num_edge].val=val;
	head[from]=num_edge; 
}
bool inq[N];
int dep[N],cur[N];
bool bfs()
{
	for(int i=1;i<=t;++i)
		inq[i]=false,dep[i]=inf,cur[i]=head[i];
	dep[s]=1;
	queue<int>q;
	q.push(s);
	while(!q.empty())
	{
		int u=q.front();q.pop();inq[u]=false;
		for(int i=head[u];i;i=e[i].nxt)
		{
			int v=e[i].to;
			if(dep[v]>dep[u]+1&&e[i].val)
			{
				dep[v]=dep[u]+1;
				if(!inq[v])inq[v]=true,q.push(v);
			}
		}
	}
	return dep[t]!=inf;
}
int maxflow;
int dfs(int u,int flow)
{
	if(u==t){maxflow+=flow;return flow;}
	int used=0,rlow;
	for(int i=head[u];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(e[i].val&&dep[v]==dep[u]+1)
		{
			rlow=dfs(v,min(e[i].val,flow-used));
			if(rlow)
			{
				used+=rlow;
				e[i].val-=rlow;
				e[i^1].val+=rlow;
			}
			if(used==flow)break;
		}
	 } 
	return used;
}
void dinic()
{
	while(bfs())dfs(s,inf);
}
int main()
{
	scanf("%d%d%d",&n,&f,&d);
	s=f+n+d+n+1;t=s+1;
	for(int i=f+1;i<=f+n;++i)
		add(i,i+n+d,1),add(i+n+d,i,0)/*,cout<<i<<" "<<i+n+d<<endl*/;
	for(int i=1;i<=f;++i)
		add(s,i,1),add(i,s,0)/*,cout<<s<<" "<<i<<endl*/;
	for(int i=1;i<=d;++i)
		add(i+f+n,t,1),add(t,i+f+n,0)/*,cout<<i+f+n<<" "<<t<<endl*/;
	for(int i=1;i<=n;++i)
	{
		int fi,di;
		scanf("%d%d",&fi,&di);
		for(int j=1,x;j<=fi;++j)
		{
			scanf("%d",&x);
			add(x,i+f,1),add(i+f,x,0)/*,cout<<x<<" "<<i+f<<endl*/;
		}
		for(int j=1,x;j<=di;++j)
		{
			scanf("%d",&x);
			add(i+n+d+f,x+f+n,1),add(x+f+n,i+n+d+f,0)/*,cout<<i+n+d+f<<" "<<x+f+n<<endl*/;
		}
	}
	dinic(); 
	printf("%d\n",maxflow);
	return 0; 
}
原文地址:https://www.cnblogs.com/zzctommy/p/12327699.html