LibreOJ #101. 最大流

Posted ZlycerQan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LibreOJ #101. 最大流相关的知识,希望对你有一定的参考价值。

二次联通门 : LibreOJ #101. 最大流

 

本想着去这个OJ刷刷板子题

结果被这道最大流给坑了。。。

10^6的网络流。。。。

一开始随手写了个dinic

交上去50

有点懵。。后又加了些奇怪的优化

还是50

 

把class封装去掉

恩, 变成70了

然后就没有然后了

TLE了一整页

 

技术分享

 

技术分享

 

后来知道要加当前弧优化才能过

就先去学。

学完后, 加上后

还是70分过不了。。非常绝望啊。。

 

/*
    LibreOJ #101. 最大流(50)
    
    Dinic + 当前弧优化
    
    用class封装了起来
    
    50分 
*/
#include <cstring>
#include <cstdio>
#include <queue>

#define Max 1000090
#define INF 1e9

void read (int &now)
{
    now = 0;
    register char word = getchar ();
    while (word < 0 || word > 9)
        word = getchar ();
    while (word >= 0 && word <= 9)
    {
        now = now * 10 + word - 0;
        word = getchar ();
    }
}

int N, M, S, T;

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

class Net_Flow_Type
{
    
    private :
        
        int __to[Max * 10];
        int __next[Max * 10];
        
        int __flow[Max * 10];
        
        int Edge_Count;
        int edge_list[Max];
        
        int deep[Max], Answer;
        
        int Queue[Max * 10];
        int Head, Tail;
        int __tech_[Max];
        
    public :
        
        Net_Flow_Type ()
        {
            Edge_Count = 1;    
            Answer = 0;
        }
        
        int Flowing (int now, int flow)
        {
            if (flow <= 0 || now == T)
                return flow;
            int pos = 0, res;
            
            for (int i = __tech_[now]; i; i = __next[i])
            {
                if (deep[__to[i]] != deep[now] + 1 || __flow[i] <= 0)
                    continue;
                res = Flowing (__to[i], min (flow, __flow[i]));
                if (res > 0)
                {
                    flow -= res;
                    pos += res;
                    
                    __flow[i] -= res;
                    __flow[i ^ 1] += res;
                    if (__flow[i])
                        __tech_[now] = i;
                        
                    if (flow <= 0)
                        return pos;
                }
            }
            return pos;
        }
        
        inline void Add_Edge (int from, int to, int flow)
        {
            Edge_Count ++;
            __to[Edge_Count] = to;
            
            __next[Edge_Count] = edge_list[from];
            edge_list[from] = Edge_Count;
            
            Edge_Count ++;
            __to[Edge_Count] = from;
                
            __next[Edge_Count] = edge_list[to];
            edge_list[to] = Edge_Count;
            
            __flow[Edge_Count - 1] = flow;
            __flow[Edge_Count] = 0;
                 
        }
        
        void Insert_edges ()
        {
            for (int i = 1, from, to, flow; i <= M; i ++)
            {
                read (from);
                read (to);
                read (flow);
                
                this->Add_Edge (from, to, flow); 
            }    
        }
        
        bool Bfs (int Start)
        {
            
            memset (deep, -1, sizeof deep);
            Head = 0, Tail = 1;
            Queue[Head] = Start;
            
            deep[Start] = 0;
            register int now;
            
            while (Head < Tail)
            {
                now = Queue[Head];
                Head ++;
                
                for (int i = edge_list[now]; i; i = __next[i])
                    if (deep[__to[i]] == -1 && __flow[i])
                    {
                        deep[__to[i]] = deep[now] + 1;
                        if (__to[i] == T)
                            return true;
                        
                        Queue[Tail ++] = __to[i]; 
                    }
            }
        
            return deep[T] != -1;
        }
        
        int Dinic ()
        {
            while (Bfs (S))
            {
                for (int i = 0; i <= N; i ++)
                    __tech_[i] = edge_list[i];
                    
                Answer += Flowing (S, INF);
            }
            
            return Answer;
        }
};

Net_Flow_Type Make;

int main (int argc, char *argv[])
{
    read (N);
    read (M);
    read (S);
    read (T);
    
    Make.Insert_edges (); 
    
    printf ("%d", Make.Dinic ());
    
    return 0;
}

 

 

 

 

/*
    LibreOJ #101. 最大流(70)
    
    Dinic + 当前弧优化
    
    没有封装
    70分
     
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#define Max 1000010
#define INF 1e8

using namespace std;

void read (int &now)
{
    now = 0;
    char word = getchar ();
    while (word < 0 || word > 9)
        word = getchar ();
    while (word >= 0 && word <= 9)
    {
        now = now * 10 + word - 0;
        word = getchar ();
    }
}
inline int min (int a, int b)
{
    return a < b ? a : b;
}

int __tech_[Max];

struct Edge
{
    int to;
    int next;
    int flow;
}edge[Max * 20];

int Edge_Count = 1, edge_list[Max];
int deep[Max];
inline void AddEdge (int from, int to, int flow)
{
    Edge_Count++;
    Edge *now = &edge[Edge_Count];
    now->flow = flow;
    now->to = to;
    now->next = edge_list[from];
    edge_list[from] = Edge_Count;
}

int N, M, S, T;

int Get_Flow (int now, int flow)
{
    if (flow <= 0 || now == T)
        return flow;
    int res = 0, pos;
    for (int i = __tech_[now]; i; i = edge[i].next)
    {
        if (deep[edge[i].to] != deep[now] + 1 || edge[i].flow <= 0)
            continue;
        pos = Get_Flow (edge[i].to, min (flow, edge[i].flow));
        res += pos;
        flow -= pos;
        edge[i].flow -= pos;
        edge[i ^ 1].flow += pos;
        if (edge[i].flow)
            __tech_[now] = i;
        if (flow <= 0)
            return res;
    }
    return res;
}

int queue[Max * 10];
int Answer;

void Bfs ()
{
    int Head, Tail;
    int now;
    bool flag;
    while (true)
    {
        memset (deep, -1, sizeof deep);
        Head = 0, Tail = 1;
        queue[0] = S;
        deep[S] = 0;
        flag = false;
        while (Head < Tail)
        {
            now = queue[Head++];
            for (int i = edge_list[now]; i; i = edge[i].next)
                if (deep[edge[i].to] < 0 && edge[i].flow)
                {
                    deep[edge[i].to] = deep[now] + 1;
                    if (edge[i].to == T)
                    {
                        flag = true;
                        break;
                    }
                    queue[Tail++] = edge[i].to;
                }
            if (flag == true)
                break;
        }
        if (deep[T] < 0)
            break;
        for (int i = 0; i <= N; i ++)
            __tech_[i] = edge_list[i];
            
        Answer += Get_Flow (S, INF);
    }
}

int main (int argc, char *argv[])
{
    read (N);
    read (M);
    read (S);
    read (T);
    int x, y, z;
    for (int i = 1; i <= M; i++)
    {
        read (x);
        read (y);
        read (z);
        AddEdge (x, y, z);
        AddEdge (y, x, 0);
    }
    Bfs ();
    printf ("%d", Answer);
    return 0;
}

 

 

 

/*
    此为std
    
    跑的飞快。。。
     
    不是很懂为什么
    明明一样的。。。
     
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int maxn=1000005;
const int INF=0x3f3f3f3f;
inline int read (int &now)
{
    now = 0;
    char word = getchar ();
    while (word < 0 || word > 9)
        word = getchar ();
    while (word >= 0 && word <= 9)
    {
        now = now * 10 + word - 0;
        word = getchar ();
    }
}
struct edge
{
    int to,rev,cap;
    edge() {}
    edge(int t,int r,int c)
    {
        to=t;
        rev=r;
        cap=c;
    }
};
vector<edge> vec[maxn];
int n,m,s,t,que[maxn],h,tail,level[maxn];
void add_edge(int from,int to,int cap)
{
    vec[from].push_back(edge(to,vec[to].size(),cap));
    vec[to].push_back(edge(from,vec[from].size()-1,0));
}
bool bfs()
{
    memset(level,-1,sizeof(level));
    level[que[h=tail=1]=s]=0;
    int x,y;
    while (h<=tail)
    {
        x=que[h++];
        for (int i=0; i<vec[x].size(); i++)
        {
            y=vec[x][i].to;
            if (vec[x][i].cap==0||level[y]!=-1) continue;
            level[y]=level[x]+1,que[++tail]=y;
        }
    }
    return level[t]!=-1;
}
int dfs(int x,int f)
{
    if (x==t) return f;
    int used=0,w,y;
    for (int i=0; i<vec[x].size(); i++)
    {
        y=vec[x][i].to;
        if (vec[x][i].cap==0||level[y]!=level[x]+1) continue;
        w=dfs(y,min(f-used,vec[x][i].cap));
        used+=w,vec[x][i].cap-=w,vec[y][vec[x][i].rev].cap+=w;
        if (used==f) return f;
    }
    if (used!=f) level[x]=-1;
    return used;
}
int max_flow()
{
    int flow=0;
    while (bfs()) flow+=dfs(s,INF);
    return flow;
}
int main()
{
    read (n);
    read (m);
    read (s);
    read (t);
    int u, v, c;
    for (int i=0; i<m; i++)
    {
        read (u);
        read (v);
        read (c);
        add_edge(u,v,c);
    }
    printf ("%d\n",max_flow());
    return 0;
}

 

以上是关于LibreOJ #101. 最大流的主要内容,如果未能解决你的问题,请参考以下文章

LibreOJ 6001 太空飞行计划(最大流)

LibreOJ 6004 圆桌聚餐 (最大流)

LibreOJ #6001. 「网络流 24 题」太空飞行计划 最大权闭合图

LibreOJ #6002. 「网络流 24 题」最小路径覆盖

LibreOJ #2006. 「SCOI2015」小凸玩矩阵

[loj#101] 最大流 网络流模板