URAL 1533 Fat Hobbits
2016-02-11 17:01
316 查看
题意
构造最长反链题解
先来回顾一下几个做法:1. 求最长链——直接DP,然后还可能可以用二分优化
2. 求最小反链覆盖——类似拓扑排序,每次把度为0的点找出来删掉即可
3. 求最小链覆盖——即是在求路径覆盖,把每个点拆成i_0,i_1,原图i->j(注意要补全所有关系),则连i_0->j_1,
(点数-最大匹配数)即为答案。构造即为把匹配边“对回去”“连起来”
4. 求最长反链——在3.那个二分图中,求一个最小点覆盖集,则i被取出当且仅当i_0,i_1均不在这个点覆盖集中。
证明:
(1)求出的点集一定满足反链。证明:如果选出的某两个点之间有边,则不符合覆盖集定义,矛盾。
(2)i_0与i_1不可能同时在点覆盖集中。证明:若如此,则|反链|>n-|最小点覆盖|=n-|最大匹配|=|最小链覆盖|=|最长链|,矛盾。
(注意3和4需要把偏序关系补全,否则会出现问题,例如1->2->3)
然后再来回顾一下二分图求最小点覆盖
1. 求最大匹配
2. 对于左边所有的未配点,做增广,并标记(此时增广一定失败,否则就不是最大匹配了)
3. 左边所有的未标记点和右边所有的已标记点即为答案。
原因:
(1) 观察所有未匹配边,因为未配边不可能两边都是未配点(否则与最大匹配矛盾)
a. 左边是未配点,此时左边的点会被增广,右边的匹配点会被标记,由(3)会被覆盖。
b. 右边是未配点,那么左边一定是已配点,这种边不可能作为增广的最后一条边(否则增广路被找到),所以左右两边点都不会被标记,由(3)会覆盖
(2) 观察所有匹配边,要么在(3)中被标记,此时右边点被标记,要么左边的点没有标记,由(3)会被覆盖
同时,所有匹配边仅有一侧被覆盖,故此时|点覆盖集|=|最大匹配|,满足定理,故是合法最小覆盖集。
code
#include<algorithm> #include<cstdio> #include<cstring> #include<cassert> using namespace std; const int maxn=110; int n; int G[maxn][maxn]; int left[maxn],right[maxn]; int S[maxn],T[maxn]; bool match(int u){ if(S[u]) return 0; S[u]=1; for(int v=1;v<=n;++v)if(G[u][v]){ if(T[v]) continue; T[v]=1; if(!left[v] || match(left[v])){ left[v]=u; right[u]=v; return 1; } } return 0; } int main(){ // freopen("in.txt","r",stdin); scanf("%d",&n); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) scanf("%d",&G[i][j]); for(int k=1;k<=n;++k) for(int i=1;i<=n;++i)if(G[i][k]) for(int j=1;j<=n;++j)if(G[k][j]) G[i][j]=1; int res=0; memset(left,0,sizeof left); memset(right,0,sizeof right); for(int i=1;i<=n;++i)if(!right[i]){ memset(S,0,sizeof S); memset(T,0,sizeof T); if (match(i)) ++res; } printf("%d\n",n-res); memset(S,0,sizeof S); memset(T,0,sizeof T); for(int i=1;i<=n;++i)if(!right[i]) match(i); int res2=0; for(int i=1;i<=n;++i)if(!(!S[i] || T[i])){ printf("%d%c",i,(++res2)==n-res ? '\n' : ' '); } // for(;;); return 0; }
相关文章推荐
- 简单的四则运算
- 数的奇偶性
- ACM网址
- 1272 小希的迷宫
- 1272 小希的迷宫
- hdu 1250 大数相加并用数组储存
- 矩阵的乘法操作
- 蚂蚁爬行问题
- 蚂蚁爬行问题
- 求两个数的最大公约数【ACM基础题】
- 打印出二进制中所有1的位置
- 杭电题目---一只小蜜蜂
- 初学图论-Kahn拓扑排序算法(Kahn's Topological Sort Algorithm)
- 初学图论-Bellman-Ford单源最短路径算法
- 初学图论-DAG单源最短路径算法
- 初学图论-Dijkstra单源最短路径算法
- 初学图论-Dijkstra单源最短路径算法基于优先级队列(Priority Queue)的实现
- HDOJ 1002 A + B Problem II (Big Numbers Addition)
- 初学ACM - 半数集(Half Set)问题 NOJ 1010 / FOJ 1207
- 初学ACM - 组合数学基础题目PKU 1833