Asteroids (匈牙利)

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

       这是为什么呢? 让我们来分析一下, 这里有一个很好的模拟过程: 将右边未匹配上的点依次加标记, 然后标记 左边与右边标记的相连的点 ,左边的点一定是最大匹配上的点,不然找到的一定不是最大匹配, 标记最大匹配且左边已经标记了的点 。 最后 取左边标记了的点 和右边未标记的点就组成了最小覆盖。 现在最大匹配的点一定都覆盖了,左边是最大匹配,右边不是的边也覆盖了, 右边是最大匹配,左边不是这种情况也覆盖了。所有情况都覆盖了 , 而左边标记了的点 由最大匹配对应的右边的点 与右边未标记的(为标记一定是最大匹配上的) 加起来就是最大匹配数。

图的独立集:寻找一个点集,其中任意两点在图中无对应边。

 

二分图的最大独立集 = 图的点数 - 最大匹配数

 

       这个比较好理解, 把最小覆盖的点去了,则图中一条边也没有了。剩下的就是最大独立集。

 

最小路径覆盖问题:用尽量少的不相交简单路径覆盖有向无环图的所有顶点。

 

将每个顶点分为两个,分别在X集合和Y集合中,如果存在有向边(a,b),对应在二分图中有(Xa,Yb)

 

 

最小路径数 = 节点数 - 最大匹配

参考 http://hi.baidu.com/desmoon/blog/item/ce5de032bc6d63f11a4cff16.html

 

 

对于任意图:

|最小边覆盖|+|最大匹配|=|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|-最大匹配

http://hi.baidu.com/edwardmj/blog/item/b5fc0419bd3661f1af513325.html


#include
<stdio.h> #include<string.h> int map[505][505]; int used[505],n; int link[505]; int findPath(int p) { for(int i=1;i<=n;i++) { if(!used[i] && map[p][i]) { used[i]=1; if(!link[i] || findPath(link[i])) { link[i]=p; return 1; } } } return 0; } int hungary() { int ans=0,i; for(i=1;i<=n;i++) { memset(used,0,sizeof(used)); if(findPath(i)) ans++; } return ans; } int main() { int k,i,u,v; memset(link,0,sizeof(link)); scanf("%d%d",&n,&k); for(i=0;i<k;i++) { scanf("%d%d",&u,&v); map[u][v]=1; } printf("%d\n",hungary()); return 0; }
posted @ 2013-12-25 15:38  单调的幸福  阅读(209)  评论(0编辑  收藏  举报