二分图

来源:互联网 发布:最红网络歌曲 2017 编辑:程序博客网 时间:2024/06/10 12:21

【二分图分类】

 

二分图匹配

POJ1469、POJ1274、POJ2239、POJ1719、POJ2446、POJ3020

 

最小点覆盖 =  最大二分匹配(每增加一条两个端点均未被选中的匹配,都会增加一个点)

POJ1325、

 

最小路径覆盖 = N - 最大二分匹配(每引入一个匹配就会减少一条路径)

POJ1422、

 

最小路径覆盖变种

POJ2594、

 

带权二分图(KM算法)

POJ2195、HDU2813、

 

最大独立数 = 顶点数 - 匹配数/2

POJ1466

 

【匈牙利算法关键代码】

 

邻接表可以在一定节省上节省时间。

 

struct node{int to;int next;}edge[maxn*maxn+5];int ect;int head[maxn+5];bool visited[maxn+5];int link[maxn+5];void insert_edge(int from, int to){edge[ect].next = head[from];edge[ect].to = to;head[from] = ect;ect++;}bool find(int v){int i;int t;for (i=head[v]; i+1!=0; i=edge[i].next){t = edge[i].to;if (!visited[t]){visited[t] = true;if (link[t]==0 || find(link[t])){link[t] = v;return true;}}}return false;}int solve(int n, int m){int i, j;int ans = 0;for (i=1; i<=n; i++){for (j=1; j<=m; j++)visited[j] = false;if (find(i))ans++;}return ans;}void init(int n, int m){int i;ect = 0;for (i=0; i<=n; i++)head[i] = -1;for (i=0; i<=m; i++)link[i] = 0;}


【KM算法关键代码】

 

邻接矩阵初始化未[-inf]

KM用于求权值和最大。

求权值和最小时初始化邻接矩阵时取其权值的相反数,结果再取相反数即可。

 

const int maxn = 200;const int inf = (1<<30);int w[maxn+5][maxn+5];int lx[maxn+5], ly[maxn+5];int linky[maxn+5];bool visx[maxn+5], visy[maxn+5];int lack;inline int min(int a, int b){    if (a<=b) return a;    else return b;}bool find(int v, int m){    int i, t;    visx[v] = true;    for (i=1; i<=m; i++)    {        if (visy[i]) continue;        t = lx[v] + ly[i] - w[v][i];        if (t==0)        {            visy[i] = true;            if (linky[i]==-1 || find(linky[i], m))            {                linky[i] = v;                return true;            }        }        else lack = min(lack, t);    }    return false;}int KM(int n, int m){    int i, j, k;    for (i=0; i<=m; i++)    {        ly[i] = 0;        linky[i] = -1;    }    for (i=1; i<=n; i++)    {        lx[i] =-inf;        for (j=1; j<=m; j++)        {            if (w[i][j]>lx[i])                lx[i] = w[i][j];        }    }    for (i=1; i<=n; i++)    {        while(true)        {            for (j=0; j<=n; j++) visx[j] = false;            for (j=0; j<=m; j++) visy[j] = false;            lack = inf;            if (find(i, m)) break;            for (j=1; j<=n; j++)            {                if (visx[j]) lx[j] -= lack;            }            for (j=1; j<=m; j++)            {                if (visy[j]) ly[j] += lack;            }        }    }    int ans = 0;    for (i=1; i<=m; i++)    {        if (linky[i]>-1)        {            ans += w[linky[i]][i];        }    }    return ans;}


 

原创粉丝点击