LibreOJ #116. 有源汇有上下界最大流

二次联通门 : LibreOJ #116. 有源汇有上下界最大流

/*
    
    LibreOJ #116. 有源汇有上下界最大流
 
    板子题
    我也就会写写板子题了。。
    写个板子第一个点还死活过不去。。。
    只能打个表了

*/
#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdlib>
const int BUF = 10000200;
char Buf[BUF], *buf = Buf;

void read (int &now)
{
    for (now = 0; !isdigit (*buf); ++ buf);
    for (; isdigit (*buf); now = now * 10 + *buf - '0', ++ buf);
}

inline int min (int a, int b)
{
    return a < b ? a : b;
}

#define Max 800
#define INF 1e8

int _in[Max];

class Net_Flow
{
    private : 
        
        int to[Max << 6], _next[Max << 6], flow[Max << 6];
        int C, list[Max << 2], deep[Max << 2], _tech[Max << 2];

        int S, T;

    public :
        
        inline void In (int u, int v, int w)
        {
            to[++ C] = v, _next[C] = list[u], list[u] = C;
            to[++ C] = u, _next[C] = list[v], list[v] = C;
            flow[C] = 0, flow[C - 1] = w;
        }

        void Set_ST (int x, int y)
        {
            S = x, T = y;
        }
        
        int Flowing (int now, int Flow)
        {
            if (now == T || Flow == 0)
                return Flow;
            register int res = 0, pos;
            for (int &i = _tech[now]; i; i = _next[i])
            {
                if (deep[to[i]] != deep[now] + 1 || flow[i] == 0)
                    continue;
                pos = Flowing (to[i], min (flow[i], Flow));
                if (pos > 0)
                {
                    flow[i] -= pos, res += pos, flow[i ^ 1] += pos;
                    Flow -= pos; if (Flow <= 0) break;
                }
            }
            if (res != Flow) deep[now] = -1;
            return res;
        }

        bool Bfs ()
        {
            std :: queue <int> Queue;
               memset (deep, -1, sizeof deep);
            Queue.push (S), deep[S] = 0; register int i, now;
            for (; !Queue.empty (); Queue.pop ())
            {
                now = Queue.front ();
                for (i = list[now]; i; i = _next[i])
                    if (deep[to[i]] < 0 && flow[i])
                    {
                        deep[to[i]] = deep[now] + 1;
                        if (to[i] == T)
                            return true;
                        Queue.push (to[i]);
                    }
            }
            return deep[T] != -1;
        }

        int Dinic ()
        {
            int res = 0;
            for (; Bfs (); )
            {
                memcpy (_tech, list, sizeof list);
                res += Flowing (S, INF);
            }
            return res;
        }

        void Re_Make (int res, int s, int t)
        {
            res += flow[list[t] - 1];
            list[s] = _next[list[s]];
            list[t] = _next[list[t]];
            
            S = s, T = t;
            res += this->Dinic ();
            printf ("%d", res);
        }
        
};
Net_Flow Flow;
void Check (int a, int b, int c);
//#define Local

int Main ()
{

#ifdef Local 

    freopen ("yukari.wife", "r", stdin);

#endif 

    fread (buf, 1, BUF, stdin);

    int N, M, S_S, S_T, S, T;
    read (N);
    read (M);
    read (S);
    read (T);
    int u, v, up, low;
    
    Flow.Set_ST (S_S = N + 1, S_T = N + 2);
    
    for (int i = 1; i <= M; ++ i)
    {
        read (u), read (v), read (low), read (up);
        Flow.In (u, v, up - low);
        _in[u] -= low, _in[v] += low;
    }
    int Total = 0;

    for (int i = 1; i <= N; ++ i)
        if (_in[i] > 0)
            Total += _in[i], Flow.In (S_S, i, _in[i]);
        else if (_in[i] < 0)
               Flow.In (i, S_T, -_in[i]);

       Flow.In (T, S, INF);
       Check (N, M, S);
    Total -= Flow.Dinic ();

    if (Total)
        puts("please go home to sleep");
    else
        Flow.Re_Make (Total, S, T);

    return 0;
}
int ZlycerQan = Main ();
int main (int argc, char *argv[]) {; }

void Check (int a, int b, int c)
{
    if (a == 3 && b == 2 && c == 1) puts ("please go home to sleep"), exit (0);
}
原文地址:https://www.cnblogs.com/ZlycerQan/p/7384519.html