hdu4292Food(最大流Dinic算法)

简介:

/*
      题意:每一个人都有喜欢的吃的和喝的,每一个人只选择一个数量的吃的和一个数量的喝的,问能满足最多的人数!?
    思路:建图很是重要!f-food, p-people, d-drink
    建图:  0(源点)--->f--->p---->p'---->d--->t(汇点)
            将人拆分很是重要,因为每一个人最多只能有一种选择,也就是p--->p'的最大流量是 1!
        如果还是不清楚,看一看下图的例子,将人拆分与不拆分的区别!
                         
  */
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#define N 850
#define M 201000
#define INF 0x3f3f3f3f
using namespace std;

struct EDGE{
    int v, cap, nt;
};

int first[N];
EDGE g[M];
int cnt;
int n, f, d;

void addEdge(int u, int v, int cap){
    g[cnt].v=v;
    g[cnt].cap=cap;
    g[cnt].nt=first[u];
    first[u]=cnt++;
    
    g[cnt].v=u;
    g[cnt].cap=0;
    g[cnt].nt=first[v];
    first[v]=cnt++;
}

int ans, ss;

queue<int>q;
int dist[N];

bool bfs(){
    memset(dist, 0, sizeof(dist));
    dist[0]=1;
    q.push(0);
    while(!q.empty()){
          int u=q.front();
        q.pop();
        for(int e=first[u]; ~e; e=g[e].nt){
               int v=g[e].v;
            int cap=g[e].cap;
            if(!dist[v] && cap>0){
                dist[v]=dist[u]+1;
                q.push(v);
            }
        }    
    }
    if(dist[ss+1]==0) return false;
    return true;
}

int dfs(int u, int flow){
    int ff;
    if(u==ss+1) return flow;
    for(int e=first[u]; ~e; e=g[e].nt){
        int v=g[e].v;
        int cap=g[e].cap;    
        if(dist[v]==dist[u]+1 && cap>0 && (ff=dfs(v, min(cap, flow)))){
            g[e].cap-=ff;
            g[e^1].cap+=ff;
            return ff;
        }
     }
    dist[u]=-1;//表示u节点不能到达汇点! 
    return 0;
}

void Dinic(){
    ans=0;
    int d;
    while(bfs())
         while(d=dfs(0, INF))
            ans+=d;
}

int main(){
    while(scanf("%d%d%d", &n, &f, &d)!=EOF){
        ss=2*n+f+d;
        cnt=0;
        memset(first, -1, sizeof(first));
        for(int i=1; i<=f; ++i){//源点到吃的建一条有向边,最大流量为吃的的数量 
            int x;
            scanf("%d", &x);
            addEdge(0, i, x);
        }

        for(int i=1; i<=d; ++i){//喝的到汇点建一条有向边,最大流量为喝的的数量
            int x;
            scanf("%d", &x);
            addEdge(n*2+f+i, ss+1, x);
        }
        for(int i=1; i<=n; ++i){//吃的到人建一条有向边,最大流量为1 
            getchar();
            for(int j=1; j<=f; ++j){
                char ch;
                scanf("%c", &ch);
                if(ch=='Y')
                    addEdge(j, f+i, 1);
            }
        }

        for(int i=1; i<=n; ++i){//人到喝的建一条有向边,最大流量为1 
            addEdge(f+i, n+f+i, 1);//人属于节点容量,将人进行拆分,因为每一个人只能有一种选择! 
            getchar();
            for(int j=1; j<=d; ++j){
                char ch;
                scanf("%c", &ch);
                if(ch=='Y')
                    addEdge(n+f+i, f+n*2+j, 1);
            }
        }

        Dinic();
        printf("%d\n", ans);
    }
    return 0;
}

目录
相关文章
|
6月前
|
算法
飞行员配对方案(Dinic求最大二分图匹配(对匈牙利算法的优化),以及二分图的建图方式)
飞行员配对方案(Dinic求最大二分图匹配(对匈牙利算法的优化),以及二分图的建图方式)
100 0
|
算法
计算机基础问题,最大流问题获突破性进展:新算法「快得离谱」
计算机基础问题,最大流问题获突破性进展:新算法「快得离谱」
|
机器学习/深度学习 算法
[洛谷 P3376] 网络最大流 | 模板 (Dinic算法) 入门
题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。 输入格式 第一行包含四个正整数 n nn,m mm,s ss,t tt,分别表示点的个数、有向边的个数、源点序号、汇点序号。 接下来M行每行包含三个正整数 ui ,vi,wi ,表示第 i 条有向边从 ui 出发,到达 vi,边权为 wi即该边最大流量为 wi)。 输出格式 一行,包含一个正整数,即为该网络的最大流。
237 0
[洛谷 P3376] 网络最大流 | 模板 (Dinic算法) 入门
|
机器学习/深度学习 算法 Java
|
算法 Java
关于最大流的EdmondsKarp算法详解
最近大三学生让我去讲课,我就恶补了最大流算法,笔者认为最重要的是让学弟学妹们入门,知道算法怎么来的?为什么是这样?理解的话提出自己的改进,然后再看看Dinic、SAP和ISAP算法….. 一、概念引入       首先要先清楚最大流的含义,就是说从源点到经过的所有路径的最终到达汇点的所有流量和。
1306 0
|
算法
GraphCuts算法解析,Graphcuts算法求最大流,最小割实例
   图割论文大合集下载: http://download.csdn.net/detail/wangyaninglm/8292305   代码: /* graph.h */ /* Vladimir Kolmogorov (vnk@cs.
1204 0
|
机器学习/深度学习 算法 JavaScript
【算法导论】最大流算法
最大流问题就是在容量容许的条件下,从源点到汇点所能通过的最大流量。 1 流网络        网络流G=(v, E)是一个有向图,其中每条边(u, v)均有一个非负的容量值,记为c(u, v) ≧ 0。
1171 0
|
29天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。