• poj 3281 最大流+建图


    很巧妙的思想

    转自:http://www.cnblogs.com/kuangbin/archive/2012/08/21/2649850.html

    本题能够想到用最大流做,那真的是太绝了。建模的方法很妙!
    题意就是有N头牛,F个食物,D个饮料。
    N头牛每头牛有一定的喜好,只喜欢几个食物和饮料。
    每个食物和饮料只能给一头牛。一头牛只能得到一个食物和饮料。
    而且一头牛必须同时获得一个食物和一个饮料才能满足。问至多有多少头牛可以获得满足。
    最初相当的是二分匹配。但是明显不行,因为要分配两个东西,两个东西还要同时满足。
    最大流建图是把食物和饮料放在两端。一头牛拆分成两个点,两点之间的容量为1.喜欢的食物和饮料跟牛建条边,容量为1.
    加个源点和汇点。源点与食物、饮料和汇点的边容量都是1,表示每种食物和饮料只有一个。
    这样话完全是最大流问题了,。

    Sample Input

    4 3 3
    2 2 1 2 3 1  //1号牛喜欢2种食物(1,2)2种饮料(3,1)
    2 2 2 3 1 2
    2 2 1 3 1 2
    2 1 1 3 3

    Sample Output

    3



      1 /*
      2 POJ 3281 最大流
      3 //源点-->food-->牛(左)-->牛(右)-->drink-->汇点
      4 //精髓就在这里,牛拆点,确保一头牛就选一套food和drink的搭配
      5 
      6 */
      7 
      8 #include<stdio.h>
      9 #include<iostream>
     10 #include<string.h>
     11 #include<algorithm>
     12 #include<queue>
     13 using namespace std;
     14 
     15 //****************************************************
     16 //最大流模板
     17 //初始化:g[][],start,end
     18 //******************************************************
     19 const int MAXN=500;
     20 const int INF=0x3fffffff;
     21 int g[MAXN][MAXN];//存边的容量,没有边的初始化为0
     22 int path[MAXN],flow[MAXN],start,end;
     23 int n;//点的个数,编号0-n.n包括了源点和汇点。
     24 
     25 queue<int>q;
     26 int bfs()
     27 {
     28     int i,t;
     29     while(!q.empty())q.pop();//把清空队列
     30     memset(path,-1,sizeof(path));//每次搜索前都把路径初始化成-1
     31     path[start]=0;
     32     flow[start]=INF;//源点可以有无穷的流流进
     33     q.push(start);
     34     while(!q.empty())
     35     {
     36         t=q.front();
     37         q.pop();
     38         if(t==end)break;
     39         //枚举所有的点,如果点的编号起始点有变化可以改这里
     40         for(i=0;i<=n;i++)
     41         {
     42             if(i!=start&&path[i]==-1&&g[t][i])
     43             {
     44                 flow[i]=flow[t]<g[t][i]?flow[t]:g[t][i];
     45                 q.push(i);
     46                 path[i]=t;
     47             }
     48         }
     49     }
     50     if(path[end]==-1)return -1;//即找不到汇点上去了。找不到增广路径了
     51     return flow[end];
     52 }
     53 int Edmonds_Karp()
     54 {
     55     int max_flow=0;
     56     int step,now,pre;
     57     while((step=bfs())!=-1)
     58     {
     59         max_flow+=step;
     60         now=end;
     61         while(now!=start)
     62         {
     63             pre=path[now];
     64             g[pre][now]-=step;
     65             g[now][pre]+=step;
     66             now=pre;
     67         }
     68     }
     69     return max_flow;
     70 }
     71 int main()
     72 {
     73     int N,F,D;
     74     while(scanf("%d%d%d",&N,&F,&D)!=EOF)
     75     {
     76         memset(g,0,sizeof(g));
     77         n=F+D+2*N+1;
     78         start=0;
     79         end=n;
     80         for(int i=1;i<=F;i++)g[0][i]=1;
     81         for(int i=F+2*N+1;i<=F+2*N+D;i++)g[i][n]=1;
     82         for(int i=1;i<=N;i++)g[F+2*i-1][F+2*i]=1;
     83         int k1,k2;
     84         int u;
     85         for(int i=1;i<=N;i++)
     86         {
     87             scanf("%d%d",&k1,&k2);
     88             while(k1--)
     89             {
     90                 scanf("%d",&u);
     91                 g[u][F+2*i-1]=1;
     92             }
     93             while(k2--)
     94             {
     95                 scanf("%d",&u);
     96                 g[F+2*i][F+2*N+u]=1;
     97             }
     98         }
     99         printf("%d
    ",Edmonds_Karp());
    100     }
    101     return 0;
    102 }
  • 相关阅读:
    第二次作业
    复盘一个商品期货的通用模型
    C#如何获取枚举(Enum)变量的值
    [C#]Socket通信BeginReceive异步接收数据何时回调Callback
    [C#]浮点数除零无法捕获异常的解决办法
    js对字符串进行编码方法总结
    web最全资源网址
    简单粗暴地理解js原型链--js面向对象编程
    常见前端九十道面试题及答案-韩烨
    C语言文件读写,复制
  • 原文地址:https://www.cnblogs.com/cnblogs321114287/p/4316354.html
Copyright © 2020-2023  润新知