P2891 [USACO07OPEN] Dining G

Sol

OK,看到题面,$s \to $ 食物 $ \to $ 奶牛 $ \to $ 饮料 $ \to t$,流量全 \(1\),太水了。

然后 \(20 pts\)

显然这个题的前面没有标“【模板】”,是不会很简单的。

为什么会错,举一个例子:

s -> Food1
s -> Food2
Food1 -> Cow
Food2 -> Cow
Cow -> Drink1
Cow -> Drink2
Drink1 -> t
Drink2 -> t

然后我们的程序成功的输出了 \(2\),是错的,因为我们没有限制每头奶牛只能有一组食物与饮料。

于是我们需要用到最大流的另一种套路——拆点,我们把奶牛拆成奶牛入点和奶牛出点,流量设 \(1\),就保证了每头奶牛最多有一组食物与饮料。

最终的建模:$s \to $ 食物 $ \to $ 奶牛入点 $ \to $ 奶牛出点 $ \to $ 饮料 $ \to t$,感觉还是好水

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long  

inline int read()
{
	int x(0);
	short f(1);
	char ch(getchar());
	while(!isdigit(ch))f=(ch=='-')?-1:1,ch=getchar();
	while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x*f;
}

const int N=2005;
class eg
{
public:
	int to,w;
	int unsigned ip;
};
int n,F,D,s,t,dep[N],hig[N];
vector<eg>nbr[N];

bool bfs()
{
	queue<int>q;
	q.push(s);
	for(int i=s;i<=t;i++)
		dep[i]=-1,hig[i]=0;
	dep[s]=0;
	while(q.empty()==false)
	{
		int cur=q.front();
		q.pop();
		for(auto dat:nbr[cur])
		{
			int nxt=dat.to,w=dat.w;
			if(w>0&&dep[nxt]==-1)
			{
				dep[nxt]=dep[cur]+1;
				q.push(nxt);
			}
		}
	}
	return dep[t]>=0;
}

int dfs(int cur,int now)
{
	if(cur==t)
		return now;
	int num=0;
	for(int i=hig[cur];i<nbr[cur].size();i=hig[cur])
	{
		hig[cur]=i+1;
		int nxt=nbr[cur][i].to,w=nbr[cur][i].w,ip=nbr[cur][i].ip;
		if(w>0&&dep[nxt]==dep[cur]+1)
		{
			int h=dfs(nxt,min(now,w));
			nbr[cur][i].w-=h;
			nbr[nxt][ip].w+=h;
			now-=h;
			num+=h;
			if(now==0)
				return num;
		}
	}
	return num;
}

void add(int x,int y,int w=1)
{
	nbr[x].push_back({y,w,nbr[y].size()});
	nbr[y].push_back({x,0,nbr[x].size()-1ull});
	return ;
}

signed main()
{
	// freopen("in.in","r",stdin
	// freopen("out,out","w",stdout);
	n=read(),F=read(),D=read();
	s=0,t=F+n+n+D+1;
	for(int i=1;i<=F;i++)
		add(s,i);
	for(int i=F+n+n+1;i<=F+n+n+D;i++)
		add(i,t);
	for(int i=1;i<=n;i++)
	{
		int fcnt(read()),dcnt(read());
		add(F+i,F+n+i);
		while(fcnt--)
		{
			int x(read());
			add(x,F+i);
		}
		while(dcnt--)
		{
			int x(read());
			add(F+n+i,F+n+n+x);
		}
	}
	int ans=0;
	while(bfs()==true)
		ans+=dfs(s,2e18);
	cout<<ans;
	return 0;
}
posted @ 2025-02-12 15:57  tmp_get_zip_diff  阅读(7)  评论(0)    收藏  举报