1. 程式人生 > >[poj] 3281 Dining

[poj] 3281 Dining

problem http 但是 ++ emp 一個 return 要求 ()

原題

題目大意

N頭奶牛,只能吃某種食物和飲料(而且只能吃特定的一份)
一種食物被一頭牛吃了之後,其余牛就不能吃了
第一行有N,F,D三個整數
接著2-N+1行代表第i頭牛,前面兩個整數是Fi與Di(食物與飲料的種類數量),接著是食物的種類與飲料的種類
要求輸出最多分配能夠滿足的牛的數量

解析

食物與牛連邊(w=1),飲料與牛連邊(w=1),源點與食物連邊(w=1),飲料與匯點連邊(w=1),這是很顯然的,但是我們要註意,為了保證每個牛鬥誌吃一個食物和一種飲料,所以我們將牛拆為兩個點,連w=1的邊。

#include<cstdio>
#include<algorithm>
#include<queue> #define N 510 using namespace std; int n,F,D,head[N],deep[N],cur[N],f[N],d[N],ans,cnt=2,s,t; queue <int> q; struct hhh { int to,next,w; }edge[160000]; int read() { int ans=0,fu=1; char j=getchar(); for (;(j<'0' || j>'9') && j!='-'
;j=getchar()) ; if (j=='-') j=getchar(),fu=-1; for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0'; return ans*fu; } void add(int u,int v,int w) { edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } bool bfs() { for
(int i=s;i<=t;i++) cur[i]=head[i],deep[i]=-1; q.push(s); deep[s]=1; while(!q.empty()) { int r=q.front(); q.pop(); for (int i=head[r],v;i;i=edge[i].next) { v=edge[i].to; if (edge[i].w>0 && deep[v]==-1) { deep[v]=deep[r]+1; q.push(v); } } } if (deep[t]!=-1) return 1; return 0; } int dfs(int x,int f) { if (x==t) return f; int ha=0,now; for (int &i=cur[x],v;i;i=edge[i].next) { v=edge[i].to; if (edge[i].w>0 && deep[v]>deep[x]) { now=dfs(v,min(f-ha,edge[i].w)); if (now) { ha+=now; edge[i].w-=now; edge[i^1].w+=now; } } if (ha==f) return ha; } return ha; } int main() { n=read(); F=read(); D=read(); s=0; t=2*n+F+D+1; for (int i=1;i<=F;i++) add(s,i,1),add(i,s,0); for (int i=1;i<=D;i++) add(2*n+F+i,t,1),add(t,2*n+F+i,0); for (int i=1;i<=n;i++) { add(i+F,i+n+F,1); add(i+n+F,i+F,0); f[i]=read(); d[i]=read(); for (int j=1,a;j<=f[i];j++) { a=read(); add(a,i+F,1); add(i+F,a,0); } for (int j=1,a;j<=d[i];j++) { a=read(); add(i+n+F,2*n+F+a,1); add(2*n+F+a,i+n+F,0); } } while(bfs()) ans+=dfs(s,0x3f3f3f3f); printf("%d",ans); return 0; }

[poj] 3281 Dining