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;
}

 

posted @ 2012-08-04 22:21  gabo  阅读(192)  评论(0编辑  收藏  举报