1. 程式人生 > >LibreOJ #101. 最大流

LibreOJ #101. 最大流

nic lan sta gis false [] 最大流 count 技術

二次聯通門 : 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. 最大流