vector實現最大流EK算法

序:
在以前的文章中實現了不利用STL實現EK算法,效率也較高。此次咱們企圖簡化代碼,減小變量的使用與手寫模擬的代碼。c++

注意:vector等STL的container在不開O2優化的時候實現同一個效果廣泛比手寫要慢。算法


源代碼以下:markdown

/* About: Max_flow_EK_vector Auther: kongse_qi Date:2017/04/22 */
#include <bits/stdc++.h>
#define INF 0x3f3f3f 
#define maxn 20005
#define maxm 200005
#define g_t Get_Int() 
#define p_b(x) push_back(x)
#define read(x) g_t, x = in
using namespace std;
/* 部分宏是爲了簡潔好看 */

struct Edge
{
    int from;
    int to;
    int weight;
    Edge(){}
    Edge(int f, int t, int w):
        from(f), to(t), weight(w){}
};//邊表

vector<Edge> edge;//存全部弧的信息
vector<int> arc[maxn];//每一個節點相連的弧的編號
typedef vector<int>::iterator iterator_t;//迭代器
int n, m, st, en, max_flow;
iterator_t pre[maxn];//記錄上一條弧的編號便於回溯
char *X, *T, *Buffer, c;//讀入優化
int in;
bool flag = true;

void Get_All()
{
    fseek(stdin, 0, SEEK_END);
    int file_lenth = ftell(stdin);
    Buffer = (char*)malloc(file_lenth);
    rewind(stdin);
    T = (X = Buffer)+fread(Buffer,1, file_lenth, stdin);
    c = *X;
}

void Get_Int()
{
    in = 0;
    while(c < '0' || c > '9')   c = *++X;
    while(c >= '0' && c <= '9')
    {
        in = in*10+c-'0';
        c = *++X;
    }
    return ;
}

void Init()//當多組數據的時候
{
    edge.resize(0);
    for(unsigned i = 0; i != n*2; ++i)
    {
        arc[i].resize(0);
    }
    max_flow = 0;
    return ;
}

void Add_Edge(int st, int en, int weight)
{
    edge.p_b(Edge(st, en, weight));
    edge.p_b(Edge(en, st, 0));//該弧信息與反向弧
    arc[st].p_b(edge.size()-2);//編號
    arc[en].p_b(edge.size()-1);
    return ;
} 

void Read()
{
    int a, b, c;
    read(n), read(m);//見宏定義
    read(st), read(en);
    for(unsigned i = 0; i != m; ++i)
    {
        read(a), read(b), read(c);
        Add_Edge(a, b, c);
    }
    return ;
}

bool Bfs(int st, int en)
{
    queue<int> q;
    int cur, ne, we;
    bool vis[maxn];
    memset(vis, 0, sizeof vis);
    q.push(st);
    vis[st] = true;
    while(!q.empty())
    {
        cur = q.front(), q.pop();
        for(iterator_t i = arc[cur].begin(); i != arc[cur].end(); ++i)//迭代器遍歷vector
        {
            ne = edge[*i].to;
            we = edge[*i].weight;
            if(vis[ne] == false && we > 0)
            {
                q.push(ne);
                pre[ne] = i;//記錄當前的弧編號
                vis[ne] = true;
                pre[ne] = i;
                if(ne == en)    return true;
            }
        }
    }
    return false;
}

void EK(int st, int en)
{
    int minn;
    while(Bfs(st, en))
    {
        minn = INF;
        for(unsigned i = en; i != st; i = edge[*pre[i]].from)
        {
            minn = min(minn, edge[*pre[i]].weight);
        }
        for(unsigned i = en; i != st; i = edge[*pre[i]].from)
        {
            edge[*pre[i]].weight -= minn;
            edge[*pre[i]^1].weight += minn;//因爲弧和它的反向弧在讀入的時候是兩兩一塊兒的,故能夠用異或獲得它反向弧的編號
        }
        max_flow += minn;   
    }
    return ;    
}


int main()
{
    freopen("test.in", "r", stdin);

    Get_All();
    Init();
    Read();
    EK(st, en);
    printf("%d\n", max_flow);

    return 0;
}

基本意思與非vector實現時是同樣的。
效率:很是慢!比非vector實現的要慢1倍,要不是讀入優化比較狠確定要超時。大數據

建議OI比賽的時候不使用STL容器,除非使用例如map等極難手寫實現的容器。
否則就等着後面的大數據TLE吧。優化

箜瑟_qi 2017.04.22 22:14ui

相關文章
相關標籤/搜索