PIGS (网络流) gzoi

广州的同学看这里:

http://www.gdgzoi.com/JudgeOnline/problem.php?cid=1045&pid=5 

Description

Mirko在一家大型养猪场工作,这家养猪场有M间可上锁的猪舍,但Mirko无法对任何一间猪舍上锁,因为他没钥匙。顾客一个接一个地到养猪场来,每个人都有一些猪舍的钥匙,他们要来买一定数量的猪。

每天早晨Mirko 所关心的数据是这一天要来养猪场的顾客,以便Mirko做好销售计划,给出要卖的猪的最大数字。

确切地讲,过程如下:顾客到养猪场,打开所有他有钥匙的猪舍,Mirko从被打开的猪舍里卖一定数量的猪给顾客,并且,如果Mirko需要,他在被打开的猪舍中重新分配剩余的猪。

在每间猪舍中猪的数量没有限制。

请编写程序,给出在一天中,Mirko可以卖出的猪的最大数量。

输入

输入的第一行给出两个整数MN,1<= M <= 1000,1<=N<=100,分别是猪舍的数量和顾客的数量。猪舍编号从1到M,顾客编号从1到N

下一行给出M个整数,表示每间猪舍在初始时猪的数量。每间猪舍里猪的数量大于等于0,小于等于1000。

然后的N行按如下形式给出顾客的记录(第i个顾客的记录在第(i+2)行):

A K1 K2 ... KA B 表示顾客拥有的猪舍的钥匙编号为K1,K2,... ,KA(按非递减序排列),并且要买B头猪。数字AB可以为0。

输出

输出的第一行且唯一的一航给出要卖猪的头数。

样例输入

样例输出

3 3

3 1 10

2 1 2 2

2 1 3 3

1 2 6

7

这道题目建图不会很困难,就是有时会想不到

1.要注意顾客是一个接一个的到来的,所以前面的顾客一定要对后面的顾客有影响。

2.我们把一个一个顾客一个接一个加入图中,也猪舍建立联系:

  (1) 若该猪舍没有被前面的人打开过,则直接与超源点连接,容量为猪舍中猪的数量。

   (2)否则,则找到最近一次打开那个猪舍的人连接,容量为INF。

3.没个顾客与超汇点连接,容量为他需要的猪的数量。

下面有一个图(样例图):

有没有发现每个点都特别有层次感:因为后面的顾客是直接受前面顾客的影响的。

接下来就是贴代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#define maxn 1005
#define INF 10000005
using namespace std;
struct Edge{
    int from,to,cap,flow;
    Edge(int u,int v,int c,int f) :from(u),to(v),cap(c),flow(f) {}
};
vector<Edge> edges;
vector<int> G[maxn];
int a[maxn];
int p[maxn];
int n,m,pig[maxn];
int flag[maxn];//注意这个flag,它记录打开猪舍的最新的顾客以及该猪舍是否被打开过;
 void AddEdge(int from,int to,int cap) {
     edges.push_back(Edge(from,to,cap,0));
     edges.push_back(Edge(to,from,0,0));
     int num=edges.size();
     G[from].push_back(num-2);
     G[to].push_back(num-1);
 }
  
 int Maxflow(int s,int t) {
     int flow=0;
     for(;;) {
         memset(a,0,sizeof(a));
         queue<int > Q;
         Q.push(s);
         a[s]=INF;
         while(!Q.empty()) {
             int x=Q.front(); Q.pop();
             for(unsigned int i=0;i<G[x].size();i++) {
                 Edge& e=edges[G[x][i]];
             if(!a[e.to] && e.cap>e.flow){
                 p[e.to]=G[x][i];
                 a[e.to]=min(a[x],e.cap-e.flow);
                 Q.push(e.to);
             }
         }
         if(a[t]) break;
         }
      if(!a[t]) break;
          for(int u=t;u!=s;u=edges[p[u]].from) {
              edges[p[u]].flow+=a[t];
              edges[p[u]^1].flow-=a[t];
          }
          flow+=a[t];
      }
      return flow;
  }
   //模板
int main()
  {std::ios::sync_with_stdio(false);
      cin>>m>>n;
      for(int i=1;i<=m;i++)
          cin>>pig[i];
      int k,exp;
      for(int i=1;i<=n;i++)
      {cin>>k;
          for(int j=1;j<=k;j++){
              cin>>exp;
              if(!flag[exp]) AddEdge(0,i,pig[exp]);//如果没被打开过,见题解2(1);
                  else AddEdge(flag[exp],i,INF);//打开过,见2(2);
                      flag[exp]=i;}
                      cin>>exp;
                      AddEdge(i,n+1,exp);//与汇点连接,见3
                  }
                  cout<<Maxflow(0,n+1)<<endl;
                  return 0;
              }
 

猜你喜欢

转载自blog.csdn.net/Wyt_code/article/details/81570932