BZOJ 1143 祭祀river【二分图之偏序集的最大反链】
2017-11-30 18:52
302 查看
传送门
//题意: 就是给定一个有向无环图, 选择尽量多的点使得其中任意的两个点都不能相互到达.
//思路:
在有向无环图中,有如下的一些定义和性质:
链:一条链是一些点的集合,链上任意两个点x, y,满足要么 x 能到达 y ,要么 y 能到达 x 。
反链:一条反链是一些点的集合,链上任意两个点x, y,满足 x 不能到达 y,且 y 也不能到达 x。
那么很显然这道题就是求最长反链长度了, 然后有以下定理:
一、有向无环图最小不相交路径覆盖
定义:用最少的不相交路径覆盖所有顶点。
定理:把原图中的每个点V拆成Vx和Vy,如果有一条有向边A->B,那么就加边Ax-By。这样就得到了一个二分图,最小路径覆盖=原图的节点数-新图最大匹配。
简单证明:一开始每个点都独立的为一条路径,总共有n条不相交路径。我们每次在二分图里加一条边就相当于把两条路径合成了一条路径,因为路径之间不能有公共点,所以加的边之间也不能有公共点,这就是匹配的定义。所以有:最小路径覆盖=原图的节点数-新图最大匹配。
二、有向无环图最小可相交路径覆盖
定义:用最小的可相交路径覆盖所有顶点。
算法:先用floyd求出原图的传递闭包,即如果a到b有路,那么就加边a->b。然后就转化成了最小不相交路径覆盖问题。
三、偏序集的最大反链
定义:偏序集中的最大独立集。
Dilworth定理:对于任意偏序集都有,最大独立集(最大反链)=最小链的划分(最小可相交路径覆盖).
通过Dilworth定理, 我们就可以把偏序集的最大独立集问题转化为最小可相交路径覆盖问题了.
然后知道这些了, 这道题就变成了裸题了…..
AC Code
//题意: 就是给定一个有向无环图, 选择尽量多的点使得其中任意的两个点都不能相互到达.
//思路:
在有向无环图中,有如下的一些定义和性质:
链:一条链是一些点的集合,链上任意两个点x, y,满足要么 x 能到达 y ,要么 y 能到达 x 。
反链:一条反链是一些点的集合,链上任意两个点x, y,满足 x 不能到达 y,且 y 也不能到达 x。
那么很显然这道题就是求最长反链长度了, 然后有以下定理:
一、有向无环图最小不相交路径覆盖
定义:用最少的不相交路径覆盖所有顶点。
定理:把原图中的每个点V拆成Vx和Vy,如果有一条有向边A->B,那么就加边Ax-By。这样就得到了一个二分图,最小路径覆盖=原图的节点数-新图最大匹配。
简单证明:一开始每个点都独立的为一条路径,总共有n条不相交路径。我们每次在二分图里加一条边就相当于把两条路径合成了一条路径,因为路径之间不能有公共点,所以加的边之间也不能有公共点,这就是匹配的定义。所以有:最小路径覆盖=原图的节点数-新图最大匹配。
二、有向无环图最小可相交路径覆盖
定义:用最小的可相交路径覆盖所有顶点。
算法:先用floyd求出原图的传递闭包,即如果a到b有路,那么就加边a->b。然后就转化成了最小不相交路径覆盖问题。
三、偏序集的最大反链
定义:偏序集中的最大独立集。
Dilworth定理:对于任意偏序集都有,最大独立集(最大反链)=最小链的划分(最小可相交路径覆盖).
通过Dilworth定理, 我们就可以把偏序集的最大独立集问题转化为最小可相交路径覆盖问题了.
然后知道这些了, 这道题就变成了裸题了…..
AC Code
const int maxn = 2e2+5; int s[maxn][maxn]; int n,m; void floyd() //求传递闭包. { for(int k=1;k<=n;k++){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ s[i][j]=min(s[i][j],s[i][k]+s[k][j]); } } } } bool vis[maxn]; int links[maxn]; vector<int>ve[maxn]; bool Find(int x) //二分图匹配. { vis[x] = 1; for(int i=0;i<ve[x].size();i++){ int m = ve[x][i]; if(vis[m]) continue; vis[m] = true; if(!links[m] || Find(links[m])){ links[m] = x; //有向图,注意标记的方向. return true; } } return false; } void solve() { scanf("%d%d" ,&n, &m); Fill(s,inf); for (int i = 1; i <= m ; i++) { int u, v; scanf("%d%d", &u, &v); s[u][v] = 1; } floyd(); for (int i = 1 ; i <= n ; i++) { for (int j = 1 ; j <= n ; j++) { if (s[i][j] != inf) { ve[i].pb(j + n); //拆点,直接加一个n即可. //千万不要忘了你建的是有向图. } } } int ans = 0; Fill(links,0); for (int i = 1 ; i <= n * 2; i++) { Fill(vis,0); if(!links[i] && Find(i)) ans++; } cout << n - ans << endl; }
相关文章推荐
- BZOJ 1143: [CTSC2008]祭祀river(二分图最大点独立集)
- BZOJ 1143: [CTSC2008]祭祀river 二分图最大点独立集
- BZOJ1143 祭祀river [二分图最大匹配]
- [1143] [CTSC2008]祭祀river(最大独立集 || 偏序集最大反链)
- 洛谷P2774 方格取数问题 BZOJ 1143祭祀river【二分图最大独立集】
- [BZOJ 1143][CTSC 2008]祭祀river(二分图最大独立集)
- bzoj 1143: [CTSC2008]祭祀river(Floyed+二分图的最大匹配)
- BZOJ 1143: [CTSC2008]祭祀river 二分图,最大独立集,Floyd闭包
- BZOJ1143:祭祀river(二分图求有向图的最大点独立集)
- BZOJ 1143 CTSC2008 祭祀river 二分图最大匹配
- [二分图最大独立集]BZOJ 1143—— [CTSC2008]祭祀river
- bzoj 1143:[CTSC2008]祭祀river 二分图最大独立集
- BZOJ 1143 祭祀 river(最大独立集)
- bzoj1143 [CTSC2008]祭祀river(最长反链长度,Floyd+二分图最大匹配)
- 【bzoj1143 CTSC2008】祭祀river(最大独立集--二分图匹配)
- BZOJ 1143 祭祀river 最长反链
- BZOJ 1143 1143: [CTSC2008]祭祀river 最长反链
- BZOJ 1143 [CTSC2008]祭祀river 二分图极大点独立集
- 【BZOJ】1143 [CTSC2008]祭祀river 二分图
- 最长反链(bzoj 1143: [CTSC2008]祭祀river)