网络流 最大流 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\n",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\n\n", kase, DC.max_flow() == full_flow ? "Yes" : "No");
        }
        return 0;
}

 

posted @ 2017-09-15 20:36  Aragaki  阅读(228)  评论(0编辑  收藏  举报