【二分图分类】
二分图匹配
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;
}