您的位置:首页 > 其它

匈牙利算法 && EK(邻接表)

2015-09-05 09:53 344 查看
/**
    用邻接表添边是图论中基础中的基础,实用价值十分可观
    添边为固定格式,理解的最好办法是画几个点,自己用手
    模拟一下添边的过程,你会感慨万千,成就感不言而喻。。

    链接表 3剑客为:edge[], edgeHead[], ne;

    edge[] 为每条边得结构体,你可以在里面放任何附加东西
    如:边权w, 流量c, 费用cost。 但v, next是最基本得两个
    变量,这决定了链接表的正常工作。。edge[u].v 即表示边 u-v
    edge[u].next 为u 连接的下条边在edge[]中的下标

    edgeHead[u] 表示节点u 在edge[] 中的位置,通过edgeHead[u]和
    edge[u].next 即可遍历连接u 的所有边,具体操作见下代码。

    特级注意:edgeHead[] 和 ne 的初始化
*/

/**
    匈牙利
*/

#include <cstring>

struct {
    int v, next;
}edge[EMax];

int edgeHead[NMax], link[NMax], vis[NMax];
int ne, n; //初始化为1  //n 为匹配点的个数
//初始化edgeHead[]数组为0
void addEdge(int u, int v) {
    edge[ne].v = v;
    edge[ne].next = edgeHead[u];
    edgeHead[u] = ne++;
}

bool dfs(int u) {
    for (int i=edgeHead[u]; i; i=edge[i].next) {
        int v = edge[i].v;
        if (!vis[v]) {
            vis[v] = true;
            if (link[v]==-1 || dfs(link[v])) {
                link[v] = u;
                return true;
            }
        }
    }
    return false;
}

int hungary() {
    int ans = 0;
    memset(link, -1, sizeof (link));
    for (int i=1; i<=n; i++) {
        memset(vis, 0, sizeof (vis));
        if (dfs(i))
            ans++;
    }
    return ans;
}

/**
    EK
*/

#include <algorithm>
#include <cstdio>
#include <csting>

const int inf = 0x3f3f3f3f;

struct {
    int u, v, c, next;
}edge[EMax];
int ne, edgeHead[NMax], pre[NMax];
int ans;

//ne 要初始化为2 因为下面找逆向边所需
//2^1 = 3  3^1 = 2
//即偶数的逆向边即为加1,奇数的逆向边减1
//没关系,即使不理解也没事,只要你相信,当你理解后你会豁然开朗你会觉得它是如此简单就好

void addEdge(int u, int v, int c) {
    edge[ne].u = u; edge[ne].v = v;
    edge[ne].c = c; edge[ne].next = edgeHead[u];
    edgeHead[u] = ne++;
    edge[ne].u = v; edge[ne].v = u;
    edge[ne].c = 0; edge[ne].next = edgeHead[v];
    edgeHead[v] = ne++;
}

bool bfs(int s, int t) {
    int que[NMax], vis[NMax], head=0, tail=1;
    memset(vis, 0, sizeof (vis));
    que[0] = s; vis[s] = true;

    while (tail > head) {
        int u = que[head++];
        for (int i=edgeHead[u]; i; i=edge[i].next) {
            int v = edge[i].v;
            if (!vis[v] && edge[i].c) {
                pre[v] = i;
                if (v == t)
                    return true;
                que[tail++] = v;
                vis[v] = true;
            }
        }
    }
    return false;
}

void end(int s, int t) {
    int i, u, sum=inf;
    for (u=t; u!=s; u=edge[i].u) {
        i = pre[u];
        sum = min(sum, edge[i].c);
    }
    for (u=t; u!=s; u=edge[u].u) {
        i = pre[u];
        edge[i].c -= sum;
        edge[i^1].c += sum;
    }
    ans += sum;
}

void EK(int s, int t) {
    while (bfs(s, t))
        end(s, t);
}

//初始化edgeHead = 0, ne = 2;

 

收藏于 2011-11-23
来自于百度空间
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: