二分图匹配总结

对于任意图:

|最小边覆盖|+|最大匹配|=|V|

二分图的最大匹配=最小点覆盖数

对于二分图:

以下数值等价.

最大匹配

最小点覆盖

|V|-最大独立集(二分图or有向无环图)

|V|-最小边覆盖数

|V|-最小路径覆盖数(有向无环图)

|V|-最小路径覆盖数/2(无向图)

(上面括号里有有向无环图的,均是将一个点拆成两个点连边匹配)

由于任意图的那几个几乎用不到于是这里只贴二分图的定义

最小点覆盖:理解为点覆盖边,即用最小的点覆盖所有的边。(若一条边的其中一个端点被选用,这条边就被覆盖了)

最大独立集:求一个最大的点集,里面的点不存在任何的边相连。

最小边覆盖:理解为边覆盖点,用最少的边把图中的点全部覆盖。

最小路径覆盖:用最少的路径把图中的所有点覆盖。

另外:最大独立集与最小覆盖集互补。

推广到有权的形式也一样,即最大点权独立集最小点权覆盖集互补

求最小点权覆盖集可以这样求:

先对图黑白染色,然后向白色的点放X部,黑色的点放Y部。

1、连边[S,i],容量等于i的点权。(对于二分图的X集)

2、连边[i,T],容量等于i的点权。(对于二分图的Y集)

3、对于有边的i和j连边[i,j](i∈X,j∈Y),容量为INF

最后得出的最大流就是最小点权覆盖,实际上是最小割与之对应。

对于求了传递闭包以后的有向无环图:

最大反链=|V|-最大匹配

[POJ 3734]找规律、等比数列求和公式

【题目大意】给定一个N个格子和4种颜色,分别是红蓝绿黄,问对于N个格子,存在多少种涂色方案,使得红格子和绿格子个数都是偶数。

【算法分析】我先写了个dfs找规律。。。发现f[i]=f(i-1)*4+2^(i-1)

于是利用我们高二刚学的等比数列求和化简,得到一个非常漂亮的式子f(n)=2^(2*n-2)+2^(n-1)。

不过比较遗憾的是偶还是不会推这个答案,于是只能找规律

【其它】1A

6412011 edward2 3734 Accepted 572K 0MS G++ 417B 2010-02-04 23:54:00

【CODE】

#include

[POJ 3627]排序、贪心

【题目大意】给定一些牛的高度,它们会玩“层层叠”,然后给定一个目标高度,求最少用多少只牛才能堆到那个高度。

【算法分析】排序,然后按大的放到小,直到>=目标高度。

水到我自己都纠结= =,会不会掉RP呢。。。

【其它】1CE悲剧。。。追求短,不打#include

6411730 edward2 3627 Accepted 244K 16MS C++ 293B 2010-02-04 22:52:15

【CODE】和A+B problem的长度有得一拼

#include

[POJ 3621]01分数规划、spfa判正权环

【题目大意】给出一个图,让你求出(点权/边权)最大的那个回路的(点权/边权)的值。

【算法分析】由于对于一个环,V=E。所以我们可以把点权赋到以这个点为起点的边上去。这样我们就可以认为点和边是一一对应的。于是他们对应的向量x也是一样的。

然后

ans=Vx/Ex

0=Vx/Ex -ans

0=(Vx-ans*Ex)/Ex

然后构造函数f(ans)=Vx-ans*Ex                     

(∵Ex>0   ∴Vx-ans*Ex=0与(Vx-ans*Ex)/Ex=0等价,且两者关于ans的单调性一致)

然后可以发现该函数关于ans递减。

然后利用二分枚举ans,再加spfa判图中是否还有正权环就可以了。

【其它】贡献3WA。。。ORZ,可恶的精度。

6411503 edward2 3621 Accepted 360K 672MS C++ 1573B 2010-02-04 22:02:39

【CODE】

#include

SEARCH总结

这段时间做了不少seach。现在来总结一下。

1、关于dfs和dfs-id。

应当考虑到的剪枝有:上界,下界,可行性剪枝,最优性剪枝。

TIPS:也许给数据排下序会有更强大的剪枝。

2、bfs

hash很重要

3、双向bfs

动态调整搜索方向很重要,即取节点少的一边去扩展。

4、A*

这个是老大,这个是重点,传说中最快的搜索。

f(s)=g(s)+h(s)——h是估价函数。

再次来重点:

估价函数h(s)的条件:1、h(s)必须是从s到达目标点的下界。2、h(s1)<=h(s2)+c[s1,s2]。c是转移代价。

然后是A*的实现:

一个堆,一个hash list(没有删除操作)。然后每次取堆顶元素(注意,堆顶元素的f值不可能再次改变)

然后扩展,如果扩展出来的节点hash list里没有,那就加入堆,否则如果扩展出来的点的F值小于堆中的,就更新堆。然后当目标节点出现在堆顶的时候,就可以输出了。因为堆顶元素的f值不可能再次改变了。