参考论文:胡伯涛《最小割模型在信息学竞赛中的应用》
闭合子图的定义:
定义一个有向图 G=(V,E) 的闭合图是该有向图的一个点集,且该点集的所有出边指向的点属于该点集,即闭合图内的任意点的任意后继也一定在闭合图中。
如何求解最大权闭合子图? 用最小割来解决。
题目: poj 2987 bzoj 1497 hdu 3879
poj 2987
构图:
void build()
{
S = n + 1, T = n + 2, ind = n + 2;
for(int i = 1, e; i <= n; i++)
{
read(e);
if(e > 0)
NewEdge(S, i, e), tot += e;
else if(e < 0)
NewEdge(i, T, -e);
else;
}
for(int i = 1, u, v; i <= m; i++)
{
read(u), read(v);
NewEdge(u, v, LINF);
}
}
bzoj 1497
构造二分图,将原图中的边视为X侧点,点视为Y侧点,它们构成依赖关系。
void init()
{
std::cin >> n >> m;
S = n + m + 1, T = n + m + 2, ind = T;
for(int i = 1; i <= T; i++) head[i] = Nya;
for(int i = 1, cost; i <= n; i++)
read(cost), NewEdge(i, T, cost);
for(int i = 1; i <= m; i++)
{
int u, v, w;
read(u), read(v), read(w);
NewEdge(S, n + i, w), ans += w;
NewEdge(n + i, u, INF);
NewEdge(n + i, v, INF);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj1497.in","r",stdin);
freopen("bzoj1497.out","w",stdout);
#endif
init();
ans -= dinic.main();
std::cout << ans;
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}
如果看不懂胡伯涛的论文,可以参考以下证明:
最大权闭合图证明:
首先引入结论,最小割所产生的两个集合中,其源点S所在集合(除去S)为最大权闭合图,接下来我们来说明一些结论。
证明:最小割为简单割。
引入一下简单割的概念:割集的每条边都与S或T关联。(请下面阅读时一定分清最小割与简单割,容易混淆)那么为什么最小割是简单割呢?因为除S和T之外的点间的边的容量是正无穷,最小割的容量不可能为正无穷。所以,得证。
证明网络中的简单割与原图中闭合图存在一一对应的关系。(即所有闭合图都是简单割,简单割也必定是一个闭合图)。
证明闭合图是简单割:如果闭合图不是简单割(反证法)。那么说明有一条边是容量为正无穷的边,则说明闭合图中有一条出边的终点不在闭合图中,矛盾。
证明简单割是闭合图:因为简单割不含正无穷的边,所以不含有连向另一个集合(除T)的点,所以其出边的终点都在简单割中,满足闭合图定义。得证。证明最小割所产生的两个集合中,其源点S所在集合(除去S)为最大权闭合图。
首先我们记一个简单割的容量为C,且S所在集合为N,T所在集合为M。
则C=M中所有权值为正的点的权值(即S与M中点相连的边的容量)+N中所有权值为负的点权值的绝对值(即N中点与T中点相连边的容量)。记(C=x1+y1);(很好理解,不理解画一个图或想象一下就明白了)。我们记N这个闭合图的权值和为W。
则W=N中权值为正的点的权值-N中权值为负的点的权值的绝对值。记(W=x2-y2);
则W+C=x1+y1+x2-y2。
因为明显y1=y2,所以W+C=x1+x2;
x1为M中所有权值为正的点的权值,x2为N中权值为正的点的权值。所以x1+x2=所有权值为正的点的权值之和(记为tot).
所以我们得到W+C= tot.整理一下 W = tot-C.
到这里我们就得到了闭合图的权值与简单割的容量的关系。因为tot为定值,所以我们欲使W最大,即C最小,即此时这个简单割为最小割,此时闭合图为其源点S所在集合(除去S)。得证。
至此,我们就将最大权闭合图问题转化为了求最小割的问题。求最小割用最小割容量=最大流,即可将问题转化为求最大流的问题。