zoukankan      html  css  js  c++  java
  • Dining(最大流建模经典例一)

     Dining

     

     题意:有N头牛,F种食物,D种饮料,每头牛都有喜欢的食物和饮料,每种饮料和食物只能分配给一头牛。最多有多少头牛能同时得到自己喜欢的食物和饮料。

    思路:源点汇点。源点与食物,饮料和汇点的边容量都是1。一头牛拆分成两个点,两点之间的容量为1。喜欢的食物和饮料跟牛建条边,容量为1。这样完全就是最大流问题了。

     图来源:here

    AC_Code:

      1 //#include <bits/stdc++.h>
      2 #include <iostream>
      3 #include <cstdio>
      4 #include <algorithm>
      5 #include <cmath>
      6 #include <queue>
      7 #include <string>
      8 #include <cstring>
      9 using namespace std;
     10 typedef long long ll;
     11 const int maxn = 1e5+10;
     12 const int mod=1e9+7;
     13 const int inf = 0x3f3f3f3f;
     14 const double pi = acos(-0.1);
     15 #define fi first
     16 #define se second
     17 #define pil pair<int,ll>
     18 #define pli pair<ll,int>
     19 #define pb push_back
     20 #define rep(i,first,second) for(int i=first;i<=second;i++)
     21 #define dep(i,first,second) for(int i=first;i>=second;i--)
     22 
     23 struct node{ int to,w,nxt; }e[maxn<<1];
     24 int n,f,d;
     25 int head[maxn<<1],dep[maxn],cnt;
     26 
     27 void add(int u,int v,int w){
     28     e[cnt].to=v;
     29     e[cnt].w=w;
     30     e[cnt].nxt=head[u];
     31     head[u]=cnt++;
     32 }
     33 
     34 bool bfs(int st,int ed){
     35     memset(dep,-1,sizeof(dep));
     36     queue<int>que;
     37     while( !que.empty()) que.pop();
     38     que.push(st);
     39     dep[st]=0;
     40     int u;
     41     while(!que.empty()){
     42         u=que.front();
     43         que.pop();
     44         for(int i=head[u];~i;i=e[i].nxt){
     45             int v=e[i].to;
     46             if( dep[v]==-1 && e[i].w>0 ){
     47                 dep[v]=dep[u]+1;
     48                 que.push(v);
     49                 if( v==ed ) return true;
     50             }
     51         }
     52     }
     53     return dep[ed]!=-1;
     54 }
     55 
     56 int dfs(int st,int ed,int flow){
     57     if( st==ed || flow==0 ) return flow;
     58     int curr=0;
     59     for(int i=head[st];~i;i=e[i].nxt){
     60         int v=e[i].to,val=e[i].w;
     61         if( dep[st]+1==dep[v] && val>0 ){
     62             int d=dfs(v,ed,min(val,flow));
     63             if( d>0 ){
     64                 e[i].w-=d;
     65                 e[i^1].w+=d;
     66                 curr+=d;
     67                 flow-=d;
     68                 if( flow==0 ) break;
     69             }
     70         }
     71     }
     72     if( curr==0 ) dep[st]=inf;
     73     return curr;
     74 }
     75 
     76 
     77 int Dinic(int st,int ed){
     78     int flow=0;
     79     while( bfs(st,ed) ){
     80         flow+=dfs(st,ed,inf);
     81     }
     82     return flow;
     83 }
     84 //节点编号:源点:0 食物:1~f 饮料:(f+1)~(f+d) 牛:(f+d+1)~(f+d+2*n) 汇点:f+d+2*n+1
     85 int main()
     86 {
     87     memset(head,-1,sizeof(head));
     88     scanf("%d%d%d",&n,&f,&d);
     89     rep(i,1,f){//源点和食物之间建边
     90         add(0,i,1);
     91         add(i,0,0);
     92     }
     93     rep(i,1,n){
     94         int fi,di;
     95         scanf("%d%d",&fi,&di);
     96         rep(j,1,fi){//食物与左牛建边
     97             int x;
     98             scanf("%d",&x);
     99             add(x,f+d+(2*i-1),1);
    100             add(f+d+(2*i-1),x,0);
    101         }
    102         rep(j,1,di){//右牛与饮料建边
    103             int x;
    104             scanf("%d",&x);
    105             add(f+d+2*i,f+x,1);
    106             add(f+x,f+d+2*i,0);
    107         }
    108     }
    109     for(int i=f+d+1;i<=f+d+2*n;i+=2){//左牛与右牛之间建边
    110         add(i,i+1,1);
    111         add(i+1,i,0);
    112     }
    113     rep(i,1,d){//饮料与汇点之间建边
    114         add(f+i,f+d+2*n+1,1);
    115         add(f+d+2*n+1,f+i,0);
    116     }
    117 
    118     int flag=Dinic(0,f+d+2*n+1);
    119     printf("%d
    ",flag);
    120     return 0;
    121 }

    还有一道类似的题:

    动物森友会(二分+网络流)

     

     题解:二分答案找最少天数+网络流

    1.建立源点,汇点

    2.源点向week1-week7连边,第i天的流量上限是

    (left ( left lfloor frac{天数}{7} ight floor+left [ 天数mod7geq i ight ] ight )cdot 每天最多完成的事件数e)

    3.因为一个事件可以在同一天举行多次,我们也不知道具体多少次,所以week向事件连边时,设流量为inf

    4.因为一个事件要完成的次数是限定的,所以我们设事件向汇点连边的容量为题目所给的ci

    5.判断所给的天数内是否向汇点流入了题目要求的事件总数。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 #define pb push_back
      5 #define fi first
      6 #define se second
      7 #define pli pair<ll,int>
      8 #define pil pair<int,ll>
      9 typedef long long ll;
     10 const int maxn = 1e4+10;
     11 const int inf = 0x3f3f3f3f;
     12 #define rep(i,first,second) for(int i=first;i<=second;i++)
     13 #define dep(i,first,second) for(int i=first;i>=second;i--)
     14 #define erep(u,i) for(int i=head[u];~i;i=e[i].nxt)
     15   
     16 struct node{int to,nxt,c;}e[maxn<<1];
     17 int head[maxn<<1],ecnt,dep[maxn];
     18 void add(int u,int v,int val){
     19     e[ecnt]=(node){v,head[u],val};
     20     head[u]=ecnt++;
     21 }
     22 void Link(int u,int v,int w){ add(u,v,w),add(v,u,0);}
     23 int dis[maxn],c[maxn];
     24   
     25 int n,E;
     26 int sum,vc;
     27 int a[maxn][10];
     28 int S,T;
     29   
     30 bool bfs(){
     31     memset(dep,-1,sizeof(dep));
     32     queue<int>que;
     33     while( !que.empty() ) que.pop();
     34     que.push(S);dep[S]=0;
     35     while( !que.empty()){
     36         int u=que.front();que.pop();
     37         erep(u,i){
     38             int v=e[i].to,w=e[i].c;
     39             if( dep[v]==-1 && w>0 ){
     40                 dep[v]=dep[u]+1;que.push(v);
     41                 if( v==T) return true;
     42             }
     43         }
     44     }
     45     return dep[T]!=-1;
     46 }
     47   
     48 int dfs(int st,int flow){
     49     if( st==T || flow==0 ) return flow;;
     50     int curr=0;
     51     erep(st,i){
     52         int v=e[i].to,val=e[i].c;
     53         if( dep[st]+1==dep[v] && val>0 ){
     54             int d=dfs(v,min(val,flow));
     55             if( d>0 ){
     56                 e[i].c-=d;e[i^1].c+=d;
     57                 curr+=d;flow-=d;
     58                 if( flow==0 ) break;
     59             }
     60         }
     61     }
     62     if( curr==0 ) dep[st]=inf;
     63     return curr;
     64 }
     65   
     66 int Dinic(){
     67     int ans=0;
     68     while( bfs() ){
     69         ans+=dfs(S,inf);
     70     }
     71     return ans;
     72 }
     73   
     74 //源点:1 汇点:2 day:3~9 事件:9+1~9+n
     75 int Check(int mid){
     76     if( E*mid<sum ) return 0;
     77     memset(head,-1,sizeof(head));ecnt=vc=0; //init
     78     S=++vc;T=++vc;                          //源点,汇点
     79   
     80     rep(i,1,7){                             //源点与day建边
     81         Link(S,++vc,(mid/7+(mid%7>=i))*E);
     82     }
     83     rep(i,1,n){
     84         vc++;
     85         Link(vc,T,c[i]);                    //事件与汇点建边
     86         rep(j,1,7){                         //事件与day建边
     87             if( a[i][j] ){
     88                 Link(j+2,vc,inf);
     89             }
     90         }
     91     }
     92     return Dinic()>=sum;
     93 }
     94 int main()
     95 {
     96     memset(head,-1,sizeof(head));
     97     scanf("%d%d",&n,&E);
     98     rep(i,1,n){
     99        scanf("%d",&c[i]);
    100        sum+=c[i];
    101   
    102        int mi;
    103        scanf("%d",&mi);
    104        rep(j,1,mi){
    105            int x;
    106            scanf("%d",&x);
    107            a[i][x]=1;
    108        }
    109     }
    110   
    111     int l=0,r=1e9/E,res;
    112     while( l<=r ){
    113         int mid=(l+r)>>1;
    114         if( Check(mid) ){
    115             r=mid-1;
    116             res=mid;
    117         }
    118         else l=mid+1;
    119     }
    120     printf("%d
    ",res);
    121   
    122     return 0;
    123 }
    View Code
  • 相关阅读:
    如何获取antlr解析的错误消息?(完美)
    2021最新版保姆级Journal Citation Reports使用
    【 Linux系统 】Centos下Linux启动时默认内核设置机制
    留言板
    友链
    java enum简记
    java enum多路分发下浅识表驱动式编程
    c语言建立和调用dll
    scanf
    js学习1 —— 类型,值,变量
  • 原文地址:https://www.cnblogs.com/wsy107316/p/12769269.html
Copyright © 2011-2022 走看看