hdu 2549 Flow Problem 最大流

hdu 2549 Flow Problem 最大流
//hdu 2549 Flow Problem 最大流

//简单最大流

//EK算法居然比 同时找多条增广路的dinic算法还快

//

//dinic要注意找不到增广路的点的层次要标为-1

//

//具体看代码



#include <iostream>

#include <stdio.h>

#include <string.h>

#include <queue>



using namespace std;



#define INF (1<<30)

#define N 25



int map[N][N], fa[N];

bool vis[N];



bool bfs(int n)

{

    memset(vis, false, sizeof(vis));

    memset(fa, -1, sizeof(fa));

    queue<int>que;

    que.push(1);

    vis[1] = true;

    while(!que.empty())     //广搜找增广路

    {

        int now = que.front();

        que.pop();

        vis[now] = true;

        for(int i = 1; i <= n; ++i)

        {

            if(vis[i] == false && map[now][i] > 0)

            {

                vis[i] = true;

                fa[i] = now;

                if(i == n)

                    return true;

                que.push(i);

            }

        }

    }

    return false;

}





void EK(int n, int m)

{

    int ans = 0;

    while(bfs(n))   //找增广路

    {

        int min = INF;//找增广路的瓶颈,也就是找到这条增广路

        for(int i = n; i != 1; i = fa[i])   //留向汇点的流量

            min = map[fa[i]][i] < min ? map[fa[i]][i] : min;



        for(int i = n; i != 1; i = fa[i])

        {

            map[fa[i]][i] -= min;

            map[i][fa[i]] += min;   //建反向边

        }

        ans += min;

    }

    printf("%d\n", ans);

}



int main()

{

    int n_case;

    scanf("%d", &n_case);

    for(int j = 1; j <= n_case; ++j)

    {

        printf("Case %d: ", j);

        int n, m;

        scanf("%d%d", &n, &m);

        memset(map, 0, sizeof(map));

        for(int i = 0; i < m; ++i)

        {

            int from, to, f;

            scanf("%d%d%d", &from, &to, &f);

            map[from][to] += f;

        }

        EK(n, m);

    }

    return 0;

}

 

dinic
#define comein freopen("in.txt", "r", stdin);

#include <stdio.h>

#include <string.h>

#include <queue>

#include <algorithm>

using namespace std;





#define INF 1<<30

#define N 2000



int eid;

int head[N], to[N], cap[N], next[N];

int level[N];



void add_edge(int from, int t, int f)

{

    to[eid] = t;

    cap[eid] = f;

    next[eid] = head[from];

    head[from] = eid++;



    to[eid] = from;   //建反向边

    cap[eid] = 0;

    next[eid] = head[t];

    head[t] = eid++;

}



bool bfs(int root, int n_point)     //残余网络分层

{

    memset(level, -1, sizeof(level));

    queue<int>que;

    que.push(root);

    level[root] = 0;

    while(!que.empty())

    {

        root = que.front();

        que.pop();

        for(int i = head[root]; i != -1; i = next[i])

        {   //边还有残余容量,且下一个点还没分层

            if(level[to[i]] == -1 && cap[i])

            {

                level[to[i]] = level[root] + 1;

                if(to[i] == n_point)

                    return true;

                que.push(to[i]);

            }

        }

    }

    return false;

}



int dfs(int root, int f, int n_point)

{

    if(root == n_point)

        return f;

    int flow, ans = 0;

    for(int i = head[root]; i != -1; i = next[i])

    {

        int m = min(cap[i], f - ans);

        if(cap[i] && level[root]+1 == level[to[i]] &&

           (flow = dfs(to[i], m, n_point ) )   )

        {   //下标从0开始,则正向边为偶数,反向边为基数;

            cap[i] -= flow;

            cap[i^1] += flow;//下标从1开始则不能用  异或

            ans += flow;

        }

    }

    if(ans == 0)    //若没找到增广路,这时注意要把该点

        level[root] = -1;   //的层次标为-1,表示不能到达

    return ans;

}



void dinic(int n_point)

{

    int flow = 0;

    while(bfs(1, n_point))  //分层

    {

        while(1)    //每条增广路都有一个瓶颈(增光路上最小容量的边)

        {   //每次分层都要把所有增广路的瓶颈都清除掉,再重新分层

            int f = dfs(1, INF, n_point);//因此最多层分v次

            if(f == 0)

                break;

            flow += f;

        }

    }

    printf("%d\n", flow);

}



int main()

{

    eid = 0;



    int n_case;

    scanf("%d", &n_case);

    for(int t = 1; t <= n_case; ++t)

    {

        printf("Case %d: ", t);

        int n_point, n_edge;

        scanf("%d%d", &n_point, &n_edge);

        memset(head, -1, sizeof(head));

        while(n_edge--)

        {

            int from, to, f;

            scanf("%d%d%d", &from, &to, &f);

            add_edge(from, to, f);

        }

        dinic(n_point);

    }

    return 0;

}

 

你可能感兴趣的:(HDU)