• [hdu4292] Food [网络流]


    题面:

    传送门

    思路:

    又是一道网络流水题......

    这道题一眼看来不难,就是一个食物和水的二分图

    但是问题来了

    怎么做到每个人只拿一份食物一份水呢?

    显然每个人分配一个点是不够的

    那我们就要使用拆点的技巧,把一个人拆成两个点,中间连一条容量为1的边,这两个点再分别和食物、水相连

    食物和源点连,水连到汇点,然后源汇最大流就是答案了、

    Code:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define inf 1e9
     6 using namespace std;
     7 inline int read(){
     8     int re=0,flag=1;char ch=getchar();
     9     while(ch>'9'||ch<'0'){
    10         if(ch=='-') flag=-1;
    11         ch=getchar();
    12     }
    13     while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
    14     return re*flag;
    15 }
    16 int n,F,D,cnt,ans,first[1010],dep[1010],cur[1010];
    17 struct edge{
    18     int to,next,w;
    19 }a[300010];
    20 inline void add(int u,int v,int w){
    21 //    cout<<"add "<<u<<ends<<v<<ends<<w<<endl;
    22     a[++cnt]=(edge){v,first[u],w};first[u]=cnt;
    23     a[++cnt]=(edge){u,first[v],0};first[v]=cnt;
    24 }
    25 void init(){
    26     memset(first,-1,sizeof(first));memset(a,0,sizeof(a));
    27     cnt=-1,ans=0;
    28 }
    29 bool bfs(int s,int t){
    30     int q[1010],head=0,tail=1,i,u,v;
    31     for(i=s;i<=t;i++) dep[i]=-1,cur[i]=first[i];
    32     dep[s]=0;q[0]=s;
    33     while(head<tail){
    34         u=q[head++];
    35         for(i=first[u];~i;i=a[i].next){
    36             v=a[i].to;
    37             if(~dep[v]||!a[i].w) continue;
    38             dep[v]=dep[u]+1;q[tail++]=v;
    39         }
    40     }
    41     return ~dep[t];
    42 }
    43 int dfs(int u,int t,int limit){
    44     if(u==t||!limit) return limit;
    45     int i,v,f,flow=0;
    46     for(i=cur[u];~i;i=a[i].next){
    47         cur[u]=i;v=a[i].to;
    48         if(dep[v]==dep[u]+1&&(f=dfs(v,t,min(limit,a[i].w)))){
    49             flow+=f;limit-=f;
    50             a[i].w-=f;a[i^1].w+=f;
    51             if(!limit) return flow;
    52         }
    53     }
    54     return flow;
    55 }
    56 void dinic(int s,int t){
    57     while(bfs(s,t)) ans+=dfs(s,t,inf);
    58 }
    59 int main(){
    60     int i,j,t1;char s[210];
    61     while(~scanf("%d%d%d",&n,&F,&D)){
    62         init();
    63         for(i=1;i<=n;i++) add(F+i,F+n+i,1);
    64         for(i=1;i<=F;i++) t1=read(),add(0,i,t1);
    65         for(i=1;i<=D;i++) t1=read(),add(F+n*2+i,F+D+n*2+1,t1);
    66         for(i=1;i<=n;i++){
    67             scanf("%s",s);
    68             for(j=1;j<=F;j++){
    69                 if(s[j-1]=='Y') add(j,F+i,inf);
    70             }
    71         }
    72         for(i=1;i<=n;i++){
    73             scanf("%s",s);
    74             for(j=1;j<=D;j++){
    75                 if(s[j-1]=='Y') add(F+n+i,F+n*2+j,inf);
    76             }
    77         }
    78         dinic(0,F+D+n*2+1);
    79         printf("%d
    ",ans);
    80     }
    81 }
  • 相关阅读:
    emlog6.0代码审计
    Linux系统
    PHP反序列化链挖掘
    Yii框架反序列化RCE利用链分析
    CVE-2020-1472漏洞复现
    linux 报错 Input/output error
    SKimage
    layui 统计行totalRow 保留两位小数
    linux清空历史命令(history)
    shred 命令详解
  • 原文地址:https://www.cnblogs.com/dedicatus545/p/8456578.html
Copyright © 2020-2023  润新知