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 

你可能感兴趣的:(HDU)