题意:
N个点M条边的有向图,给出如下两种操作。
删除点i的所有出边,代价是Ai。
删除点j的所有入边,代价是Bj。
求最后删除图中所有的边的最小代价。
其实就是二分图最小点权覆盖。
定义:从x或者y集合中选取一些点,使这些点覆盖所有的边,并且选出来的点的权值尽可能小。
题解:
拆点。n个点拆成2n个点(左右各n个,i与(i+n)对应,之间连容量INF的边),S和i连容量为Ai的边,(i+n)与T之间连容量为Bi的边,求最小割即可
这样做为什么对呢?
当一条边存在的条件就是网络中还存在从S到T的非满流边!
方案输出不多说。。
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 }