hdu 2063 过山车

//最近在看最大流 就那这题练练 开始用EK写的 tle。。。看来EK真的过时了
//dinic 真快
#include <iostream>
using namespace std;

const
int MAXN = 510;
const
int MAXM = 1010;
int
k, n, m;
typedef struct

{

    int
v, next, cost;
}
Edge;

Edge e[MAXM*4];
int
p[MAXN*2], q[MAXN*2], level[MAXN*2], que_st[MAXN*2];
int
Start, End;

void
init()
{
//初始化 静态邻接表
    scanf("%d %d", &n, &m);
    Start = 0, End = n+m+1;
    int
i, ind = 0;
    memset(p, -1, sizeof(p));
    for
(i = 1; i <= n; ++i)
    {

        e[ind].v = i;
        e[ind].cost = 1;
        e[ind].next = p[Start];
        p[Start] = ind++;
        e[ind].v = Start;
        e[ind].cost = 0;
        e[ind].next = p[i];
        p[i] = ind++;
    }

    for
(i = 1; i <= m; ++i)
    {

        e[ind].v = End;
        e[ind].cost = 1;
        e[ind].next = p[i+n];
        p[i+n] = ind++;
        e[ind].v = i+n;
        e[ind].cost = 0;
        e[ind].next = p[End];
        p[End] = ind++;
    }

    for
(i = 0; i < k; ++i)
    {

        int
from, to;
        scanf("%d %d", &from, &to);
        e[ind].v = n + to;
        e[ind].cost = 1;
        e[ind].next = p[from];
        p[from] = ind++;
        e[ind].v = from;
        e[ind].cost = 0;
        e[ind].next = p[to+n];
        p[to+n] = ind++;
    }
}


int
Dinic()
{

    int
Max_Flow = 0;

    while
(true)
    {

        int
front = 0, last = 0, i;
        for
(i = 0; i <= n+m+1; ++i)
        {

            level[i] = 0;
        }


        level[Start] = 1;
        que_st[front] = Start;
        while
(front <= last)
        {
//bfs求层次图
            int t = que_st[front++];
            for
(i = p[t]; i != -1; i = e[i].next)
            {

                if
(e[i].cost && !level[e[i].v])
                {

                    level[e[i].v] = level[t] + 1; que_st[++last] = e[i].v;
                }
            }
        }

        if
(!level[End])
        {
//汇点不在层次图内 退出
            break;
        }

       
        for
(i = 0; i <= n+m+1; ++i)
        {

            q[i] = p[i];
        }

        last = -1;   
        while
(true)
        {
//栈模拟dfs  用dfs进行增广       
            if (last < 0)
            {
//栈空
                for (i = q[Start]; i != -1; i = e[i].next)
                {
//找与源点相邻的边
                    if (e[i].cost && q[e[i].v] != -1 && level[e[i].v] == 2)
                    {

                        break
;
                    }
                }

                if
(i >= 0)
                {

                    que_st[++last] = i;
                    q[Start] = e[i].next;
                }

                else

                {
//与源点相连的边都被删除
                    break;
                }
            }

            int
u = e[que_st[last]].v; //栈中最后的那个顶点
            if (u == End)
            {
//u为汇点 说明找到增广路
                int min = 0XFFFFFFF;
                int
index = -1;
                for
(i = 0; i <= last; ++i)
                {

                    if
(e[que_st[i]].cost < min)
                    {
//可增广的最大值
                        min = e[que_st[i]].cost;
                        index = i;
                    }
                }

                Max_Flow += min;
                for
(i = 0; i <= last; ++i)
                {
//对增广路进行增广
                    e[que_st[i]].cost -= min;
                    e[que_st[i]^1].cost += min;
                }

                //后退至删边后原增广路中可到达的最远点
                last = index - 1;
            }

            else

            {
//u不是汇点
                for (i = q[u]; i != -1; i = e[i].next)
                {
//找与u相邻的边
                    if (e[i].cost && q[e[i].v] != -1 && level[e[i].v] == level[u] + 1)
                    {

                        break
;
                    }
                }

                if
(i >= 0)
                {
//找到 则入栈
                    que_st[++last] = i;
                    q[u] = e[i].next;
                }

                else

                {
//否则 删除点u和与u相邻的所有边
                    last--;
                    q[u] = -1;
                }
            }
        }
    }

    return
Max_Flow;
}

int
main()
{

    while
(scanf("%d", &k) != EOF && k)
    {

        init();
        printf("%d\n", Dinic());
    }

    return
0;
}

posted on 2009-08-16 14:34  ZAFU_VA  阅读(458)  评论(0编辑  收藏  举报

导航