对于每个点有两个数in[i],out[i],表示拆掉i的所有入边的代价和拆掉所有出边的代价
对于一条边(u,v)有两种操作可以将其拆掉,要么拆除u的所有出边,要么拆除v的所有入边,两个操作至少要有一个被执行
这就相当于最小点权覆盖(可以参考那篇最小割的论文)中的一条边中的任意一个点都可以覆盖这条边
所以,一个操作看做一个点,一条边相当于连接两个操作的边,一个最小点权覆盖的模型就建立好了
建图过程如下:
新建源点汇点s、t
对于每个点u,拆成u u+n
s->u 容量为out【u】;
u+n->t容量为in[u]
对于每条边u->v
u->v+n,容量为无穷大
求最小割,可得最小代价,(画个简单的图模拟一下就知道为什么这样子是对的啦)
然后是输出方案
直接从s开始搜,(1-n)中不能搜到的点为选择拆除出边操作的点
(n+1-->2*n)中能搜到的点为选择拆除入边操作的点,因为已经求过最小割了,所以这些点(s能搜到的)与t可定已经分开了
注意:最小割对应的是简单割(因为中间的边都有无穷大的容量),哪条边被割了,就相当于选择了对应的某个操作
比如
与源点连接的边是割边,表示拆除a的出边这个操作
与汇点。。。。。。
附一张简单的图
图中拆除a的出边要花费10,拆除b、c的入边都花费4,最小割为8,
所以肯定是选择了b+n->t与c+n->t这两条割边,即选择了拆除b的入边,与拆除c的入边这两个操作
如果两个4变为两个6,则最小割容量为10,选择s->a这条割边,即选择拆除a的出边这个操作
这样子讲,应该比较清楚了吧
#include<stdio.h>
#include<string.h>
const int MAX=1010;