hdu 4292 Food (成都赛区 网络赛 最大流 )

http://acm.hdu.edu.cn/showproblem.php?pid=4292

题意:

给出n个人喜欢的饮料种类以及食物种类,每个人只能取其中一种且数量为1,现在给出有f中食物以及d种饮料,以及他们各自的数量,问如何安、排食物以及饮料,使得最多的人得到一个食物以及一瓶饮料
题解 :

最大流 + 拆点 ;

为了 保证 每一个人只有 一个 食物和 饮料 ,我们 要将  一个人 拆分成 2 个 ,他们之间 连线 流量 为 1 ;

  1 #include<cstdio>
  2  #include<cstring>
  3  #include<cmath>
  4  #include<iostream>
  5  #include<algorithm>
  6  #include<set>
  7  #include<map>
  8  #include<queue>
  9  #include<vector>
 10  #include<string>
 11 #define INF 0x3fffffff
 12 #define F(x) (x)
 13 #define N(x) (205+(x))
 14 #define CPN(x) (410+(x))
 15 #define D(x) (615+(x))
 16 #define maxn 250
 17 #define CL(a,b) memset(a,b,sizeof(a))
 18 #define Pnum 210
 19 using namespace std;
 20 
 21  int next[maxn*20],dis[maxn*10];
 22  int s,e;
 23  int  n, fnum ,dnum ,f[maxn],d[maxn],cnt;
 24  struct node
 25  {
 26      int to;
 27      int cap ;
 28      int next ;
 29  }p[200000] ;
 30   int que[maxn*maxn] ,idx;
 31 
 32  void add(int x,int y,int cap)
 33  {
 34      p[cnt].to = y;
 35      p[cnt].cap = cap ;
 36      p[cnt].next = next[x];
 37      next[x] = cnt++ ;
 38 
 39      p[cnt].to = x;
 40      p[cnt].cap = 0;
 41      p[cnt].next = next[y];
 42      next[y] = cnt++ ;
 43  }
 44  int bfs()// 重新 建 图 (按 层数 建图)
 45  {
 46 
 47      memset(dis,0xff,sizeof(dis)) ;
 48      dis[s] = 0 ;
 49      queue<int>que;
 50      que.push(s);
 51 
 52      while(!que.empty())
 53      {
 54 
 55          int  k = que.front();que.pop() ;
 56          forint i = next[k];i!=-1;i = p[i].next)
 57          {
 58              int v = p[i].to;
 59 
 60 
 61              int cap = p[i].cap ;
 62 
 63              if(cap > 0 && dis[v] < 0 )// 如果 可以  可以到达 但 还没有 访问
 64              {
 65 
 66                  dis[v] = dis[k]+ 1 ;
 67                  que.push(v) ;
 68              }
 69          }
 70 
 71      }
 72 
 73 
 74      if(dis[e] > 0return 1;
 75      else return  0 ;
 76 
 77  }
 78 
 79  
 80 
 81  int  dfs(int x,int mx)// 查找  路径上的 最小 的 流量
 82  {
 83 
 84      int i , a ,tf =  0;
 85 
 86      if(x == e) return mx ;
 87 
 88      for(i = next[x];i!= - 1;i = p[i].next)
 89      {
 90          int v = p[i].to ;
 91          int cap = p[i].cap ;
 92          if(cap > 0 && dis[v] == dis[x] + 1  && (a =dfs(v,min(cap,mx))))
 93          {
 94 
 95              p[i].cap -= a;
 96              p[i^1].cap += a;
 97 
 98                return a;
 99 
100 
101          }
102      }
103      if(!tf) dis[x] = -1;// 没有 找到 最小流量 ,说明 从这个点到不了 终点 ,所以  标记一下
104      return tf ;
105  }
106 
107 
108 
109 
110  
111  int main()
112  {
113     int i , j ;
114     char c[250] ;
115      //freopen("data.txt","r",stdin) ;
116     while(scanf("%d%d%d",&n,&fnum,&dnum)!=EOF)
117     {
118 
119         CL(next,-1) ;
120         cnt = 0;
121          s = 0;
122          e = 2000;
123          for(i = 1 ; i <= fnum;i++)
124          {
125              scanf("%d",&f[i]);
126          }
127          for(i = 1 ; i<= dnum;i++)
128          {
129              scanf("%d",&d[i]) ;
130          }
131          for(i = 1; i <= n;i++)//  人 和 吃的
132          {
133              scanf("%s",c);
134              for(j = 0 ;  j< fnum ;j++)
135              {
136                  if(c[j] == 'Y')
137                  {
138 
139                      add(j + 1,i + Pnum,1) ;
140                  }
141              }
142 
143          }
144          for(i = 1; i<= n;i++)//  人 和 喝的
145          {
146              scanf("%s",c);
147              for(j = 0 ;  j< dnum ;j++)
148              {
149                  if(c[j] == 'Y')
150                  {
151 
152                      add(i + Pnum*2,j + Pnum*3 + 1,1) ;
153                  }
154              }
155 
156          }
157          for(i = 1; i <= fnum;i++)//增加源点
158          {
159 
160              add(0,i,f[i]) ;
161          }
162          for(i = Pnum*3  + 1,j = 1; j <= dnum;i++,j++)//增加 汇点
163          {
164 
165              add(i,e,d[j]) ;
166 
167          }
168 
169          for(i = 1; i <= n;i++)//  将人 拆分
170          {
171 
172              add(i + Pnum,i +Pnum*2,1);
173          }
174            int ans = 0;
175        int res;
176 
177        while(bfs())
178        {
179 
180 
181           while(res = dfs(s,INF)) ans+= res ;
182 
183        }
184        printf("%d\n",ans);
185     }
186  }
187 
原文地址:https://www.cnblogs.com/acSzz/p/2695938.html