• LibreOJ #101. 最大流


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

    2017.6.24 

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

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

    10^6的网络流。。。。

    一开始随手写了个dinic

    交上去50

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

    还是50

    把class封装去掉

    恩, 变成70了

    然后就没有然后了

    TLE了一整页

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

    就先去学。

    学完后, 加上后

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

    2017.6.25 

     

      好吧。。

      有一句话一直没加。。。

      是在Flowing函数里的

      if (flow != pos)

        deep[now] = -1;

      这个才是精髓啊。。

    /*
        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
    ",max_flow());
        return 0;
    }

    自己的AC代码:

    #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], std :: 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;
                    }
                }
                if (pos != flow)
                    deep[now] = -1;
                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)
            {
                
                for (int i = 0; i <= N; i ++)
                    deep[i] = -1;
                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;
    }
  • 相关阅读:
    我的游戏开发工作生涯要开始了
    关于碰撞检测和物理引擎
    关于havok
    认识多渲染目标(Multiple Render Targets)技术
    无限分级的tree
    运用ThreadLocal解决jdbc事务管理
    盒子模型 计算
    监听域对象
    爱恨原则 就近原则 (LVHA)
    java database connection
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/7074577.html
Copyright © 2020-2023  润新知