zoukankan      html  css  js  c++  java
  • 网络流 最大流 Drainage Ditches Dinic

    hdu 1532 

    题目大意:

          就是由于下大雨的时候约翰的农场就会被雨水给淹没,无奈下约翰不得不修建水沟,而且是网络水沟,并且聪明的约翰还控制了水的流速,本题就是让你求出最大流速,无疑要运用到求最大流了。题中N为水沟数,M为水沟的顶点,接下来Si,Ei,Ci分别是水沟的起点,终点以及其容量。求源点1到终点M的最大流速。注意重边

    Dinic算法的实现有以下几个步骤:

    1:初始化容量网络和网络流

    2:构造残留网络和层次网络,若汇点不在层次网络中则算法结束 输出最大流

    3:在层次网络中用一次DFS进行增广,DFS执行完毕,该阶段的增广也就完毕了。

    4:转至步骤2

    #include<iostream>
    using namespace std;
    #include<cstdio>
    #include<queue>
    #define INF 0x7fffffff
    #define min(a,b) a<b?a:b
    int N,M;
    int level[205];
    int Si,Ei,Ci;
    struct Dinic
    {
        int c;
        int f;
    }edge[205][205];
    bool dinic_bfs()//构造层次网络
    {
        queue<int> Q;
        memset(level,0,sizeof(level));//初始化顶点的层次 为0
        Q.push(1);
        level[1]=1;
        int u,v;
        while(!Q.empty())
        {
            u=Q.front();
            Q.pop();
            for(v=1;v<=M;v++)
            {
                if(!level[v]&&edge[u][v].c>edge[u][v].f)//即顶点未被访问过,顶点u,v,存在边
                {
                    level[v]=level[u]+1;//给顶点标记层次
                    Q.push(v);
                }
            }
        }
        return level[M]!=0;//若返回false表明 汇点不在层次网络中
    }
    int dinic_dfs(int u,int cp)//进行增广
    {
        int tmp=cp;
        int v,t;
        if(u==M)
            return cp;
        for(v=1;v<=M&&tmp;v++)
        {
            if(level[u]+1==level[v])
            {
                if(edge[u][v].c>edge[u][v].f)
                {
                    t=dinic_dfs(v,min(tmp,edge[u][v].c-edge[u][v].f));
                    edge[u][v].f+=t;
                    edge[v][u].f-=t;
                    tmp-=t;
                }
            }
        }
        return cp-tmp;
    }
    int dinic()//求出最大流
    {
        int sum,tf;
        sum=tf=0;
        while(dinic_bfs())
        {
            while(tf=dinic_dfs(1,INF))
            {
                sum+=tf;
            }
        }
        return sum;
    }
    int main()
    {
        while(~scanf("%d%d",&N,&M))
        {
            memset(edge,0,sizeof(edge));
            while(N--)
            {
                scanf("%d%d%d",&Si,&Ei,&Ci);
                edge[Si][Ei].c+=Ci;//防止重边
            }
            int S=dinic();
            printf("%d
    ",S);
        }
        return 0;
    }
    
    
    
    </span>

     hdu 3572 

    题意:

           给N个任务,M台机器。每个任务有最早才能开始做的时间S,deadline E,和持续工作的时间P。每个任务可以分段进行,但是在同一时刻,一台机器最多只能执行一个任务. 问存不存在可行的工作时间。

    分析:

           由于时间<=500且每个任务都能断断续续的执行,那么我们把每一天时间作为一个节点来用网络流解决该题.

           建图: 源点s(编号0), 时间1-500天编号为1到500, N个任务编号为500+1 到500+N, 汇点t(编号501+N).

           源点s到每个任务i有边(s, i, Pi)

           每一天到汇点有边(j, t, M) (其实这里的每一天不一定真要从1到500,只需要取那些被每个任务覆盖的每一天即可)

           如果任务i能在第j天进行,那么有边(i, j, 1) 注意由于一个任务在一天最多只有1台机器执行,所以该边容量为1,不能为INF或M哦.

    最后看最大流是否等于所有任务所需要的总天数.

    #include <bits/stdc++.h>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #define INF 1e9
    using namespace std;
    const int maxn = 1000 + 10;
    
    struct Edge
    {
            int from, to, cap, flow;
            Edge() {}
            Edge(int f, int t, int c, int fl): from(f), to(t), cap(c), flow(fl) {}
    };
    
    struct Dinic
    {
            int n, m, s, t;
            vector<Edge> edges;
            vector<int> G[maxn];
            bool vis[maxn];
            int cur[maxn];
            int d[maxn];
    
            void init(int n, int s, int t)
            {
                    this->n = n, this->s = s, this->t = t;
                    edges.clear();
                    for (int i = 0; i < n; ++i)
                    {
                            G[i].clear();
                    }
            }
    
            void AddEdge(int from, int to, int cap)
            {
                    edges.push_back( Edge(from, to, cap, 0) );
                    edges.push_back( Edge(to, from, 0, 0) );
                    m = edges.size();
                    G[from].push_back(m - 2);
                    G[to].push_back(m - 1);
            }
    
            bool BFS()
            {
                    queue<int> Q;
                    memset(vis, 0, sizeof(vis));
                    vis[s] = true;
                    d[s] = 0;
                    Q.push(s);
                    while (!Q.empty())
                    {
                            int x = Q.front();
                            Q.pop();
                            for (int i = 0; i < G[x].size(); ++i)
                            {
                                    Edge& e = edges[G[x][i]];
                                    if (!vis[e.to] && e.cap > e.flow)
                                    {
                                            vis[e.to] = true;
                                            d[e.to] = d[x] + 1;
                                            Q.push(e.to);
                                    }
                            }
                    }
                    return vis[t];
            }
    
            int DFS(int x, int a)
            {
                    if (x == t || a == 0)
                    {
                            return a;
                    }
                    int flow = 0, f;
                    for (int &i = cur[x]; i < G[x].size(); ++i)
                    {
                            Edge &e = edges[G[x][i]];
                            if (d[e.to] == d[x] + 1 && (f = DFS(e.to, min(a, e.cap - e.flow) ) ) > 0)
                            {
                                    e.flow += f;
                                    edges[G[x][i] ^ 1].flow -= f;
                                    flow += f;
                                    a -= f;
                                    if (a == 0)
                                    {
                                            break;
                                    }
                            }
                    }
                    return flow;
            }
    
            int max_flow()
            {
                    int ans = 0;
                    while (BFS())
                    {
                            memset(cur, 0, sizeof(cur));
                            ans += DFS(s, INF);
                    }
                    return ans;
            }
    } DC;
    
    int full_flow;
    
    int main()
    {
            int T;
            scanf("%d", &T);
            for (int kase = 1; kase <= T; ++kase)
            {
                    int n, m;
                    scanf("%d%d", &n, &m);
                    full_flow = 0;
                    int src = 0, dst = 500 + n + 1;
                    DC.init(500 + 2 + n, src, dst);
                    bool vis[maxn];//表示第i天是否被用到
                    memset(vis, 0, sizeof(vis));
    
                    for (int i = 1; i <= n; ++i)
                    {
                            int P, S, E;
                            scanf("%d%d%d", &P, &S, &E);
                            DC.AddEdge(src, 500 + i, P);
                            full_flow += P;
                            for (int j = S; j <= E; ++j)
                            {
                                    DC.AddEdge(500 + i, j, 1);
                                    vis[j] = true;
                            }
                    }
    
                    for (int i = 1; i <= 500; ++i)if (vis[i]) //被任务覆盖的日子才添加边
                            {
                                    DC.AddEdge(i, dst, m);
                            }
                    printf("Case %d: %s
    
    ", kase, DC.max_flow() == full_flow ? "Yes" : "No");
            }
            return 0;
    }
  • 相关阅读:
    242
    241
    240
    「音乐」(G)I-DLE—화(火花) (HWAA)
    「音乐」Red Velvet—Psycho
    「音乐」Taylor Swift—the lakes (bonus track)
    「笔记」DP简单笔记
    「游记」CSP2020-S2游记
    「音乐」BLACKPINK-Ice Cream (with Selena Gomez)
    matlab 2021a linux 版本下载
  • 原文地址:https://www.cnblogs.com/Aragaki/p/7528305.html
Copyright © 2011-2022 走看看