POJ 2125 最小割

题意:

N个点M条边的有向图,给出如下两种操作。
删除点i的所有出边,代价是Ai。
删除点j的所有入边,代价是Bj。
求最后删除图中所有的边的最小代价。

其实就是二分图最小点权覆盖。

定义:从x或者y集合中选取一些点,使这些点覆盖所有的边,并且选出来的点的权值尽可能小。

题解:

拆点。n个点拆成2n个点(左右各n个,i与(i+n)对应,之间连容量INF的边),S和i连容量为Ai的边,(i+n)与T之间连容量为Bi的边,求最小割即可

这样做为什么对呢?

当一条边存在的条件就是网络中还存在从S到T的非满流边!

方案输出不多说。。

 

View Code
 1 #include <cstdio>

 2 #include <cstring>

 3 #include <cstdlib>

 4 #include <iostream>

 5 

 6 #define N 300

 7 #define M 20000

 8 #define INF 99999999

 9 

10 using namespace std;

11 

12 int to[M],next[M],head[N],len[M],cnt,layer[N],n,m,S,T,q[M];

13 bool vis[N];

14 

15 inline void add(int u,int v,int w)

16 {

17     to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;

18     to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++;

19 }

20 

21 void read()

22 {

23     memset(head,-1,sizeof head);cnt=0;

24     scanf("%d%d",&n,&m);

25     S=0,T=n+n+1;

26     for(int i=1,a;i<=n;i++) scanf("%d",&a),add(i+n,T,a);

27     for(int i=1,a;i<=n;i++) scanf("%d",&a),add(S,i,a);

28     for(int i=1,a,b;i<=m;i++) scanf("%d%d",&a,&b),add(a,b+n,INF);

29 }

30 

31 bool bfs()

32 {

33     memset(layer,-1,sizeof layer);

34     int h=1,t=2,sta;

35     q[1]=S; layer[S]=0;

36     while(h<t)

37     {

38         sta=q[h++];

39         for(int i=head[sta];~i;i=next[i])

40             if(len[i]>0&&layer[to[i]]<0)

41             {

42                 layer[to[i]]=layer[sta]+1;

43                 q[t++]=to[i];

44             }

45     }

46     return layer[T]!=-1;

47 }

48 

49 int find(int u,int cur_flow)

50 {

51     if(u==T) return cur_flow;

52     int result=0,tmp;

53     for(int i=head[u];~i;i=next[i])

54         if(len[i]>0&&layer[to[i]]==layer[u]+1)

55         {

56             tmp=find(to[i],min(cur_flow-result,len[i]));

57             len[i]-=tmp; len[i^1]+=tmp; result+=tmp;

58         }

59     if(!result) layer[u]=-1;

60     return result;

61 }

62 

63 void dfs(int u)

64 {

65     vis[u]=true;

66     for(int i=head[u];~i;i=next[i])

67         if(!vis[to[i]]&&len[i])

68             dfs(to[i]);

69 }

70 

71 void dinic()

72 {

73     int ans=0;

74     while(bfs()) ans+=find(S,INF);

75     printf("%d\n",ans);

76     dfs(S);

77     ans=0;

78     for(int i=1;i<=n;i++)  

79         ans+=(!vis[i])+(vis[i+n]);  

80        printf("%d\n",ans);

81     for(int i=1;i<=n;i++)  

82     {  

83         if(!vis[i]) printf("%d -\n",i);

84         if(vis[i+n]) printf("%d +\n",i);

85     }

86 }

87 

88 int main()

89 {

90     read();

91     dinic();

92     return 0;

93 }

 

 

你可能感兴趣的:(poj)