POJ 2152 Destroying The Graph【最小点权覆盖+最小割】
2012-08-11 19:05
357 查看
题意: 有一个有 N 个节点M 条边的的有向图,每个点对应两种操作:
将该点所有入边删除 ‘+’ ,对应一个花费,将该点所有出边删除 ‘ - ’亦对应一个花费
问如何操作将所有边删除使得花费的总和最小。
分析: 建图:
将每个点拆分成两个点, i(左点) 和 i+n(右点) ,
建立一个源点 s=0,汇点 u=2*n+1
在源点和每个点左面的点连一条边,容量为删除出边的费用
在汇点和每个点右面的点连一条边,容量为删除入边的费用
如果有 u 到 v 的边,在u 和 v +n 之间连一条边,容量为无穷大
求出最大流即最小割
从源点深搜找出残流不为 0 的点,把这些点标记掉,剩下的为标记的点即为删除的顶点。
将该点所有入边删除 ‘+’ ,对应一个花费,将该点所有出边删除 ‘ - ’亦对应一个花费
问如何操作将所有边删除使得花费的总和最小。
分析: 建图:
将每个点拆分成两个点, i(左点) 和 i+n(右点) ,
建立一个源点 s=0,汇点 u=2*n+1
在源点和每个点左面的点连一条边,容量为删除出边的费用
在汇点和每个点右面的点连一条边,容量为删除入边的费用
如果有 u 到 v 的边,在u 和 v +n 之间连一条边,容量为无穷大
求出最大流即最小割
从源点深搜找出残流不为 0 的点,把这些点标记掉,剩下的为标记的点即为删除的顶点。
#include<stdio.h> #include<string.h> #include<stdlib.h> #define INF 0x1f1f1f1f #define min(a,b)(a)<(b)?(a):(b) #define clr(x)memset(x,0,sizeof(x)) #define maxn 210 struct node { int c,next,to; }e[100000]; int tot; int head[maxn]; void add(int s,int t,int flow) { e[tot].to=t; e[tot].c=flow; e[tot].next=head[s]; head[s]=tot++; } int max_flow(int st,int end,int n) { int numh[maxn],h[maxn],edge[maxn],pre[maxn]; int cur_flow,maxflow=0,u,tmp,neck,i; clr(h); clr(numh); memset(pre,0xff,sizeof(pre)); for(i=0;i<=n;i++) edge[i]=head[i]; numh[0]=n+1; u=st; while(h[st]<n+1) { if(u==end) { cur_flow=INF; for(i=st;i!=end;i=e[edge[i]].to) if(cur_flow>e[edge[i]].c) { neck=i; cur_flow=e[edge[i]].c; } for(i=st;i!=end;i=e[edge[i]].to) { tmp=edge[i]; e[tmp].c-=cur_flow; e[tmp^1].c+=cur_flow; } maxflow+=cur_flow; u=neck; } for(i=edge[u];i!=-1;i=e[i].next) if(e[i].c&&h[u]==h[e[i].to]+1) break; if(i!=-1) { edge[u]=i; pre[e[i].to]=u; u=e[i].to; } else { if(--numh[h[u]]==0) break; edge[u]=head[u]; for(tmp=n,i=head[u];i!=-1;i=e[i].next) if(e[i].c) tmp=min(tmp,h[e[i].to]); h[u]=tmp+1; ++numh[h[u]]; if(u!=st) u=pre[u]; } } return maxflow; } int v[maxn]; void dfs(int r) { v[r]=1; int i,k; for(i=head[r];i!=-1;i=e[i].next) { k=e[i].to; if(!v[k]&&e[i].c) { v[k]=1; dfs(k); } } } int main() { int i,n,m,s,u,p,a,b,res,num; while(scanf("%d%d",&n,&m)!=EOF) { s=0; u=2*n+1; memset(head,0xff,sizeof(head)); tot=0; for(i=1;i<=n;i++) { scanf("%d",&p); add(i+n,u,p); add(u,i+n,0); } for(i=1;i<=n;i++) { scanf("%d",&p); add(s,i,p); add(i,s,0); } while(m--) { scanf("%d%d",&a,&b); add(a,b+n,INF); add(b+n,a,0); } res=max_flow(s,u,n*2+1); num=0; clr(v); dfs(s); for(i=1;i<=n;i++) { if(!v[i]) num++; if(v[i+n]) num++; } printf("%d\n%d\n",res,num); for(i=1;i<=n;i++) { if(!v[i]) printf("%d -\n",i); if(v[i+n]) printf("%d +\n",i); } } return 0; }
相关文章推荐
- POJ 2125 Destroying The Graph 二分图最小点权覆盖集
- poj 2125 Destroying The Graph 最小点权覆盖集
- POJ 2125 Destroying The Graph(二分图最小点权覆盖)
- POJ 2125 Destroying The Graph 二分图 最小点权覆盖
- POJ 2125 Destroying The Graph 二分图 最小点权覆盖
- POJ 2125 Destroying The Graph (dinic求最小点权覆盖)
- 图论(网络流,二分图最小点权覆盖):POJ 2125 Destroying The Graph
- POJ 2125 Destroying The Graph 二分图最小点权覆盖 最小割
- POJ 2125 Destroying The Graph 最小点权覆盖集
- POJ 2125 --Destroying The Graph【最小割解决 "最小点权覆盖问题" && 输出解(割边集) && 各种不懂】
- poj 2125 Destroying The Graph (最小点权覆盖)
- 【POJ】2125 Destroying The Graph 最小点权覆盖
- POJ 2125 Destroying The Graph 二分图 最小点权覆盖
- poj 2125 Destroying The Graph(最小割,最小点权覆盖)
- POJ 2125 Destroying The Graph(最小割-最小点权覆盖)
- poj 2125 Destroying The Graph 最小点权覆盖
- Destroying The Graph (poj 2125 最小点权覆盖)
- POJ 2125 Destroying the Graph 二分图最小点权覆盖
- POJ 2125 Destroying The Graph 二分图 最小点权覆盖
- POJ 2125 Destroying The Graph 最小点权覆盖