POJ-DINNIG

30 篇文章 1 订阅

这道题真的很难想到是用最大流做得,主要是建图,大概就是这样:

然后每条边得容量为1.

然后牛和牛之间好像必须有对应得一条边,因为如果不这样的话,比如我们寻求增广路的时候,第一次选了f1、1号牛、d1,然后继续寻找可能就会找到f1、1号牛、d2。而如果加个牛和牛之间的边,恰好解决了这个问题,构思非常妙。下面是用ff板子做的:

import java.util.*;
public class Main {
	static int map[][];				//建图
	static int pre[];				//储存增广路径
	static boolean used[];				//是否用过
	static int s,t;					//源点和汇点
	static int n;					//储存节点个数
	static boolean bfs(){			//寻找增广路径
		for(int i=1;i<=n;i++){pre[i]=0;used[i]=false;}
		used[s]=true;
		LinkedList<Integer> q=new LinkedList<Integer>();
		q.add(s);
		while(!q.isEmpty()){
			int cur=q.poll();
			if(cur==t)return true;
			for(int i=1;i<=n;i++){
				if(!used[i]&&map[cur][i]!=0){
					 pre[i]=cur;
					 q.offer(i);
					 used[i]=true;
				}
			}
		}
		return false;
	}
	static int maxPath(){
		int ans=0;
		while(bfs()){
			int min=Integer.MAX_VALUE;
			for(int i=t;i!=s;i=pre[i])
				min=Math.min(min,map[pre[i]][i]);
			ans+=min;
			for(int i=t;i!=s;i=pre[i]){
				map[pre[i]][i]-=min;
				map[i][pre[i]]+=min;
			}
		}
		return ans;
	}
	static void init(){
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				map[i][j]=0;
	}
	public static void main(String[] args) {
		map=new int[1000][1000];
		pre=new int[1000];
		used=new boolean[1000];
		Scanner sc=new Scanner(System.in);
		int m=sc.nextInt();
		int f=sc.nextInt();
		int d=sc.nextInt();
		
		//总点数为2*m+f+d+2,源点为2*m+f+d+1,汇点为2*m+f+d+2
		n=m+f+d+2;
		s=m+f+d+1;
		t=m+f+d+2;
		init();
		
		//输入牛和食物,并在其中建边
		for(int i=1;i<=m;i++){
			int a=sc.nextInt();
			int b=sc.nextInt();
			while(a--!=0){
				int fi=sc.nextInt();
				map[fi][f+i]=1;
			}
			while(b--!=0){
				int di=sc.nextInt();
				map[f+i][f+m+di]=1;
			}	
		}
		
		//食物和源点建边
		for(int i=1;i<=f;i++)
			map[s][i]=1;
		
		//饮料和汇点建边
		for(int i=1;i<=d;i++)
			map[f+m+i][t]=1;
		System.out.println(maxPath());
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值