这两题基本一样
POJ 3281
题意:
有N个牛,F个食物,D个饮料,每个牛只吃其中若干种食物和饮料,规定每个牛要么不吃,要么食物和饮料各吃一种,各种食物和饮料都只有一个。求最多多少牛能得到满足(吃食物+饮料)
输入格式:
给牛的数量N,食物数量F,饮料数量D
接下来的N行(1到N号牛),然后TF,TD,接下来TF个食物编号,TD个饮料编号,表示 i 号牛只吃这TF个食物,TD个饮料
建图:
首先知道要把牛分点,分为牛1,牛2,如果不分则建图为
食物->牛->饮料,若牛选了食物A,饮料B,则若食物C,饮料D也跟牛有边,则被算法认为是增广路,但这并不满足每牛只能吃一种饮料和食物。
所以要变为:
源点S->食物->牛1->牛2->饮料->汇点T,所有容量为1。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define eps 10^(-6)
#define Q_CIN ios::sync_with_stdio(false)
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define CLR( a , x ) memset ( a , x , sizeof (a) )
#define RE freopen("1.in","r",stdin);
#define WE freopen("1.out","w",stdout);
#define MOD 10009
#define NMAX 10002
#define min(a,b) ((a)>(b)?(b):(a))
#define max(a,b) ((a)<(b)?(b):(a))
const int inf=0x3f3f3f3f;
const int maxn=2*100+105+105;
int ss,tt;
int cap[maxn][maxn],dis[maxn];
int bfs(int s,int t)
{
queue<int>q;
q.push(s);
CLR(dis,-1);
dis[s]=0;
while(!q.empty()){
int tmp=q.front();q.pop();
FOR(i,s,t){
if(dis[i]<0&&cap[tmp][i]){
dis[i]=dis[tmp]+1;
q.push(i);
}
}
}
if(dis[t]>0) return 1;
return 0;
}
int dfs(int s,int t,int low){
int flow;
if(s==t) return low;
FOR(i,ss,tt){ //ss->tt
if(cap[s][i]
&&(dis[i]==dis[s]+1)
&&(flow=dfs(i,t,min(cap[s][i],low)))){
cap[s][i]-=flow;
cap[i][s]+=flow;
return flow;
}
}
return 0;
}
int main()
{
// freopen("1.in","r",stdin);
int n,f,d;
int tf,td,tx;
while(cin>>n>>f>>d){
ss=0,tt=2*n+f+d+1;
CLR(cap,0);
FOR(i,1,n){
cin>>tf>>td;
while(tf--){
cin>>tx;
tx+=2*n;
cap[ss][tx]=1; //src to food
cap[tx][i]=1; //food to cow
}
while(td--){
cin>>tx;
tx+=2*n+f;
cap[tx][tt]=1; //drink to end
cap[i+n][tx]=1; //cow to drink
}
cap[i][i+n]=1; //cow1 to cow2
}
int ans=0;
while(bfs(ss,tt)){
ans+=dfs(ss,tt,inf);
}
cout<<ans<<endl;
}
}
HDU 4292 Food
此题邻接矩阵Dinic过不了,邻接表600MS,在DFS中加个//dis[u]=-1;就100MS!
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define eps 10^(-6)
#define Q_CIN ios::sync_with_stdio(false);
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define CLR( a , x ) memset ( a , x , sizeof (a) );
#define RE freopen("1.in","r",stdin);
#define WE freopen("1.out","w",stdout);
#define MOD 10009
#define debug(x) cout<<#x<<":"<<(x)<<endl;
#define sc(x) scanf("%d",&x);
#define lson i<<1,l,m
#define rson i<<1|1,m+1,r
const int maxn=805;
const int maxm=200005;
const int inf=0x3f3f3f3f;
int dis[maxn];
int ss,tt;
int cnt;
int head[maxn],q[maxn];
struct Edge
{
int v,w,next;
}edge[maxm*2];
void addEdge(int u,int v,int w)
{
edge[cnt].v=v,edge[cnt].w=w,edge[cnt].next=head[u];head[u]=cnt++;
edge[cnt].v=u,edge[cnt].w=0,edge[cnt].next=head[v];head[v]=cnt++;
}
void init()
{
CLR(head,-1);
cnt=0;
}
int bfs()
{
queue<int>q;
q.push(ss);
CLR(dis,-1);
dis[ss]=0;
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(edge[i].w&&dis[v]<0)
{
dis[v]=dis[u]+1;
q.push(v);
}
}
}
return dis[tt]>0;
}
//int bfs() //居然比STL慢10多ms
//{
// int first=0,tail=0;
// q[tail++]=ss;
// CLR(dis,-1);
// dis[ss]=0;
// while(first<tail)
// {
// int u=q[first++];
// for(int i=head[u];i!=-1;i=edge[i].next)
// {
// int v=edge[i].v;
// if(edge[i].w && dis[v]<0)
// {
// dis[v]=dis[u]+1;
// q[tail++]=v;
// }
// }
// }
// return dis[tt]>0;
//}
int dfs(int u,int low)
{
int flow;
if(u==tt) return low;
for(int i=head[u];i!=-1;i=edge[i].next)
{
if(edge[i].w
&& (dis[edge[i].v]==dis[u]+1)
&& (flow = dfs(edge[i].v,min(low,edge[i].w)))){
edge[i].w-=flow;
edge[i^1].w+=flow;
return flow;
}
}
dis[u]=-1;
return 0;
}
int maxFlow()
{
int ans=0,tans;
while(bfs())
while(tans=dfs(ss,inf))
ans+=tans;
return ans;
}
int main()
{
// RE
int n,f,d,tw;
char s1[205];
char ch;
while(scanf("%d%d%d",&n,&f,&d)!=EOF)
{
init();
ss=0,tt=2*n+f+d+1;
FOR(i,1,f) //food:1-f
{
scanf("%d",&tw);
addEdge(ss,i,tw);
}
FOR(i,1,d) //drink:1+f+2*n ~ d+f+2*n
{
scanf("%d",&tw);
addEdge(i+f+2*n,tt,tw);
}
FOR(i,1,n)
{
scanf("%s",s1);
FOR(j,1,f)
{
if(s1[j-1]=='Y'){
addEdge(j,f+i,1); //food:1~n people1:f+1~f+n
}
}
addEdge(i+f,i+f+n,1);
}
FOR(i,1,n)
{
scanf("%s",s1);
FOR(j,1,d)
{
if(s1[j-1]=='Y')
addEdge(i+f+n,j+f+2*n,1); //people2:f+n+1~f+n+n drink:f+d+2*n+1~f+d+2*n+d
}
}
printf("%d\n",maxFlow());
}
return 0;
}