POJ - 1149 PIGS(网络流经典)

题目链接

题意:

给定$M$个猪圈,一开始这些都是上了锁的;

现在$Mike$知道所有要来买猪的顾客的信息:

$1.$顾客拥有的钥匙。

$2.$顾客想要购买的数量。

销售过程为:当每个顾客到来的时候,他将他拥有钥匙的猪圈全部打开,$Mike$从这些猪圈中挑选一些猪卖给他们;

如果$Mike$愿意,他可以重新分配这些被打开的猪圈中的猪,顾客离开时,这些猪圈将被再次锁上,计算$Mike$卖出猪的最大数目。

思路:

设定超级源点和汇点,然后将第一次访问该猪圈的顾客与源点相连,流量为猪圈中猪的数目

顾客$x$紧跟顾客$y$之后打开某个猪圈,那么就将两者相连,流量为$inf$(因为在这之前$Mike$有机会调整)

将每个顾客与汇点相连,流量为改顾客想买的猪的数量。

  1 /*
  2 *  Author: windystreet
  3 *  Date  : 2018-08-16 11:29:37
  4 *  Motto : Think twice, code once.
  5 */
  6 #include <stdio.h>
  7 #include <algorithm>
  8 #include <string.h>
  9 #include <vector>
 10 #include <queue>
 11 
 12 using namespace std;
 13 
 14 #define X first
 15 #define Y second
 16 #define eps  1e-5
 17 #define gcd __gcd
 18 #define pb push_back
 19 #define PI acos(-1.0)
 20 #define lowbit(x) (x)&(-x)
 21 #define bug printf("!!!!!\n");
 22 #define mem(x,y) memset(x,y,sizeof(x))
 23 
 24 typedef long long LL;
 25 typedef long double LD;
 26 typedef pair<int,int> pii;
 27 typedef unsigned long long uLL;
 28 
 29 const int maxn = 1e3+7;
 30 const int INF  = 1<<30;
 31 const int mod  = 1e9+7;
 32 struct Edge{
 33      int from,to,cap,flow;
 34 };
 35 int f[maxn];           // 记录前一个访问过该猪圈的人
 36 int pig[maxn];         // 记录每个猪圈原来有多少猪
 37 vector<int>v[maxn];    // 记录每个人有的钥匙
 38 struct Dinic
 39 {
 40     int n,m,s,t;
 41     vector<Edge>edge;
 42     vector<int>G[maxn];
 43     bool vis[maxn];
 44     int d[maxn];
 45     int cur[maxn];
 46     void init(int n){
 47         this->n = n;
 48         for(int i=0;i<=n;i++)G[i].clear(),edge.clear();
 49     }
 50     inline void addedge(int from,int to,int cap){
 51         edge.pb((Edge){from,to,cap,0});
 52         edge.pb((Edge){to,from,0,0});
 53         m = edge.size();
 54         G[from].pb(m-2);
 55         G[to].pb(m-1);
 56     }
 57     inline bool bfs(){
 58         mem(vis,0);
 59         queue<int>Q;
 60         Q.push(s);
 61         d[s] = 0;
 62         vis[s] = 1;
 63         while(!Q.empty()){
 64             int x = Q.front(); Q.pop();
 65             int sz = G[x].size();
 66             for(int i=0;i<sz;++i){
 67                 Edge &e = edge[G[x][i]];
 68                 if(!vis[e.to] && e.cap>e.flow){
 69                     vis[e.to] = 1 ;
 70                     d[e.to] = d[x] + 1;
 71                     Q.push(e.to); 
 72                 }
 73             }
 74         }
 75         return vis[t];
 76     }
 77     int dfs(int x,int a){
 78         if(x == t || a == 0)return a;
 79         int flow = 0,f;
 80         int sz = G[x].size();
 81         for(int &i = cur[x];i<sz;i++){
 82             Edge &e = edge[G[x][i]];
 83             if(d[x] + 1 == d[e.to] && (f = dfs(e.to,min(a,e.cap - e.flow)))>0){
 84                 e.flow += f;
 85                 edge[G[x][i]^1].flow -=f;
 86                 flow += f;
 87                 a -= f;
 88                 if(a==0)break;
 89             }
 90         }
 91         //if(!flow) d[x] = -2;  //炸点优化
 92         return flow;
 93     }
 94     inline int maxflow(int s,int t){
 95         this->s = s; this -> t = t;
 96         int flow = 0;
 97         while(bfs()){
 98             mem(cur,0);
 99             flow += dfs(s,INF);
100         }
101         return flow;
102     }
103 };
104 Dinic dinic;
105 
106 void solve(){
107     int n,m,x,y;
108     scanf("%d%d",&m,&n);
109     int S = 0,T = n +1;
110     for(int i=1;i<=m;i++)scanf("%d",pig+i);
111     for(int i=1;i<=n;i++){
112         scanf("%d",&x);
113         while(x--){
114             scanf("%d",&y);
115             v[i].pb(y);                     // 记录钥匙
116         } 
117         scanf("%d",&y); 
118         dinic.addedge(i,T,y);              // 将每个人与汇点相连,流量为他需要买的猪
119     }
120     for(int i=1;i<=n;i++){
121         int sz = v[i].size();
122         for(int j=0;j<sz;j++){
123             int id = v[i][j];
124             if(!f[id]){                    // 若没有被访问过,则将该人和源点相连
125                 f[id] = i;
126                 dinic.addedge(S,i,pig[id]);
127             }else{
128                 dinic.addedge(f[id],i,INF);
129                 f[id] = i;                 // 否则就将其与上一个访问的人相连
130             }
131         }
132     }
133     printf("%d\n",dinic.maxflow(S,T));
134     
135     return;
136 }
137 
138 int main()
139 {
140 //    freopen("F:\\in.txt","r",stdin);
141 //    freopen("out.txt","w",stdout);
142 //    ios::sync_with_stdio(false);
143     int t = 1;
144     //scanf("%d",&t);
145     while(t--){
146     //    printf("Case %d: ",cas++);
147         solve();
148     }
149     return 0;
150 }

 

posted @ 2018-08-16 13:25  windystreet  阅读(243)  评论(0编辑  收藏  举报