【BZOJ1280】Emmy賣豬pigs 最大流
阿新 • • 發佈:2017-06-13
mes 事先 == 經典 include sof 打開 鑰匙 zoj
第一行有兩個整數:M和N,表示豬圈數和顧客數。 第二行有M個整數,表示每個豬圈初始時有多少豬。 接下來的N行按照前來的次序描述了每一個顧客,每行的格式如下: A K1 K2…KA B A表示該顧客擁有的鑰匙數,K1...KA表示每個鑰匙所對應的豬圈,B表示該顧客需要購買的豬的數目。
3 1 10
2 1 2 2
2 1 3 3
1 2 6
【BZOJ1280】Emmy賣豬pigs
Description
Emmy在一個養豬場工作。這個養豬場有M個鎖著的豬圈,但Emmy並沒有鑰匙。顧客會到養豬場來買豬,一個接著一個。每一位顧客都會有一些豬圈的鑰匙,他們會將這些豬圈打開並買走固定數目的豬。 所有顧客有的鑰匙和他們需要買豬的數量在事先都告訴了Emmy,於是Emmy要訂一個計劃,使得賣出去的豬最多。 買賣的過程是這樣的:一個顧客前來,並打開所有他可以打開的豬圈。然後Emmy從這些豬圈裏牽出固定數目的豬賣給顧客(最多只能和顧客需要數相等),並可以重新安排這些開著的豬圈中的豬。 每個豬圈可以存放任意數目的豬。 寫一個程序,使得Emmy能夠賣出去盡可能多的豬。Input
Output
僅包含一個整數,即最多能賣出去的豬的數目。Sample Input
3 33 1 10
2 1 2 2
2 1 3 3
1 2 6
Sample Output
7HINT
1 ≤ M ≤ 1000
1 ≤ N ≤ 100
題解:經典的最大流模型,昨天發現在BZ上並沒有A,於是重新寫一發~
先建出這樣一個naive的模型
1.將每個豬圈都拆成n個,然後從S向所有各自的第一個豬圈連邊,容量為初始豬數,各自的豬圈向下一個顧客的對應豬圈連邊,容量INF
2.從每個顧客需要的豬圈想顧客連邊,容量INF,從顧客向T連邊,容量為顧客要買的豬數,從顧客向這些豬圈連邊,容量INF
發現所有跟中間狀態的豬圈連的邊都是INF,說明這些點根本沒有必要存在,於是我們直接將中間狀態的豬圈縮掉,改為直接從顧客向顧客連邊就行了。
#include <cstdio> #include <cstring> #include <iostream> #include <queue> using namespace std; int m,n,cnt,ans,tot,S,T; int pre[1010],d[100000],next[1000000],val[1000000],head[100000],to[1000000]; queue<int> q; int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘)f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+gc-‘0‘,gc=getchar(); return ret*f; } void add(int a,int b,int c) { to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++; to[cnt]=a,val[cnt]=0,next[cnt]=head[b],head[b]=cnt++; } int dfs(int x,int mf) { if(x==T) return mf; int i,k,temp=mf; for(i=head[x];i!=-1;i=next[i]) { if(d[to[i]]==d[x]+1&&val[i]) { k=dfs(to[i],min(temp,val[i])); if(!k) d[to[i]]=0; val[i]-=k,val[i^1]+=k,temp-=k; if(!temp) break; } } return mf-temp; } int bfs() { memset(d,0,sizeof(d)); while(!q.empty()) q.pop(); int i,u; q.push(S),d[S]=1; while(!q.empty()) { u=q.front(),q.pop(); for(i=head[u];i!=-1;i=next[i]) { if(!d[to[i]]&&val[i]) { d[to[i]]=d[u]+1; if(to[i]==T) return 1; q.push(to[i]); } } } return 0; } int main() { m=rd(),n=rd(); int i,j,a,b,c; S=0,T=n+m+1; memset(head,-1,sizeof(head)); for(i=1;i<=m;i++) pre[i]=i,add(S,i,rd()); for(i=1;i<=n;i++) { a=rd(); for(j=1;j<=a;j++) b=rd(),add(pre[b],i+m,1<<30),pre[b]=i+m; add(i+m,T,rd()); } while(bfs()) ans+=dfs(S,1<<30); printf("%d",ans); return 0; }
【BZOJ1280】Emmy賣豬pigs 最大流