vector实现最大流EK算法

7 篇文章 0 订阅
5 篇文章 0 订阅

序:
在之前的文章中实现了不利用STL实现EK算法,效率也较高。这次我们企图简化代码,减少变量的使用与手写模拟的代码。

注意:vector等STL的container在不开O2优化的时候实现同一个效果普遍比手写要慢。


源代码如下:

/*
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:14

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值