1. 程式人生 > 其它 >網路流專題

網路流專題


很明顯的一道最大流匹配題目
唯一要注意的點是題目要求是一頭牛隻能搭配一個飲料和事物
所以要拆點

點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
#define INF 0x7fffffff
const int maxn=505;
const int maxm=200000;
int N,F,D,cnt,S,T;
int head[maxm],num[maxn],maxflow;
struct node{
	int to,next,w;
}edg[maxm];
void add(int u,int v,int w){
	++cnt;
	edg[cnt].to=v;
	edg[cnt].w=w;
	edg[cnt].next=head[u];
	head[u]=cnt;
}
queue<int>Q;
bool bfs(){
	while(!Q.empty()){
	   Q.pop();
	}
	for(int i=S;i<=T+N;i++)num[i]=-1;
	num[S]=1;
	Q.push(S);
	while(!Q.empty()){
		int now=Q.front();Q.pop();
		for(int i=head[now];i;i=edg[i].next){
		int to=edg[i].to,w=edg[i].w;
		if(w&&num[to]==-1){
			num[to]=num[now]+1;
			Q.push(to);
		}
		} 
	} 
	return (num[T]!=-1);
}
int dfs(int u,int f){
	if(u==T){
		return f;
	}
	int flow;
	for(int i=head[u];i;i=edg[i].next){
		int to=edg[i].to,w=edg[i].w;
		if(w&&num[to]==num[u]+1&&(flow=dfs(to,min(f,w)))){
			edg[i].w-=flow;
			edg[i^1].w+=flow;
			return flow;
		}
	}
	return 0;
}
void dinic(){
	int minn;
	while(bfs()){
		while(minn=dfs(S,INF)){
			maxflow+=minn;
		}
	}
}
int main(){
	scanf("%d%d%d",&N,&F,&D);
	cnt++;
	S=1,T=1+N+F+D+1;
	for(int i=1;i<=F;i++)add(S,i+1,1),add(i+1,S,0);
	for(int i=1;i<=D;i++)add(i+1+F+N,T,1),add(T,i+1+F+N,0);
	for(int i=1;i<=N;i++)add(1+F+i,1+F+N+D+1+i,1),add(1+F+N+D+i+1,1+F+i,0);
	for(int i=1;i<=N;i++){
		int ff,dd;
		scanf("%d%d",&ff,&dd);
		for(int t,j=1;j<=ff;j++){
			scanf("%d",&t);
			add(t+1,1+F+i,1);
			add(1+F+i,t+1,0);
		}
		for(int t,j=1;j<=dd;j++){
			scanf("%d",&t);
			add(1+F+N+D+1+i,1+F+N+t,1);
			add(1+F+N+t,1+F+N+D+1+i,0);
		}
	}
	dinic();
	printf("%d\n",maxflow);
     return 0;
}