构图思路:

1.将所有顶点v拆成两个点, v1,v2

2.源点S与v1连边,容量为 W-

3.v2与汇点连边,容量为 W+

4.对图中原边( a, b ), 连边 (a1,b2),容量为正无穷大

则该图的最小割(最大流)即为最小花费。

简单证明: 根据ST割集的定义,将顶点分成两个点集。所以对于原图中的边(a,b),转换成 S->a1->b2->T. 则此时路径必定存在

一条割边,因为a1->b2为无穷大,所以割边必定是 S->a1 or b2->T,  若为前者则意味着删除a顶点的W-,后者则是b顶点的W+.

所以该图最小割即为最小花费。

计算方案: 对于构图后跑一次最大流,然后对于残留网络进行处理,首先从源点S出发,标记所有能访问到的顶点,这些顶点即为S割点集中

的顶点。 其他则为T集合中顶点, 然后从所有边中筛选出( A属于S,B属于T,且(A,B)容量为0 )的边,即为割边。因为我们的W+/W-边都只有一条,

且都分开了。比较容易处理。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<vector>
#include<algorithm>
using namespace std; const int MAXN = ;
const int MAXM = ;
const int inf = 0x3f3f3f3f;
int A[MAXN], B[MAXN];
struct Edge{
int u, v, f, nxt;
}edge[];
int head[MAXN], idx;
int n, m;
int S, T, N; void AddEdge(int u,int v,int f){
edge[idx].u = u, edge[idx].v = v, edge[idx].f = f;
edge[idx].nxt = head[u]; head[u] = idx++;
edge[idx].u = v, edge[idx].v = u, edge[idx].f = ;
edge[idx].nxt = head[v]; head[v] = idx++;
} int h[MAXN], vh[MAXN];
int dfs(int u,int flow){
if(u == T) return flow;
int tmp = h[u]+, sum = flow;
for(int i = head[u]; ~i; i = edge[i].nxt){
if( edge[i].f && (h[edge[i].v]+ == h[u]) ){
int p = dfs( edge[i].v, min(sum,edge[i].f));
edge[i].f-=p, edge[i^].f+=p, sum-=p;
if( sum== || h[S]==N ) return flow-sum;
}
}
for(int i = head[u]; ~i; i = edge[i].nxt)
if( edge[i].f ) tmp = min( tmp, h[edge[i].v] );
if( --vh[ h[u] ] == ) h[S] = N;
else ++vh[ h[u]=tmp+ ];
return flow-sum;
}
int sap(){
int maxflow = ;
memset(h,,sizeof(h));
memset(vh,,sizeof(vh));
vh[] = N;
while( h[S] < N ) maxflow += dfs( S, inf );
return maxflow;
} bool vis[MAXN];
int res[MAXM]; void DFS(int u ){
vis[u] = true;
for(int i = head[u]; ~i; i = edge[i].nxt ){
int v = edge[i].v;
if( !vis[v] && edge[i].f )
DFS( v );
}
}
void solve(){
int maxflow = sap();
printf("%d\n", maxflow );
memset( vis,,sizeof(vis));
DFS( S ); int cnt = ;
for(int i = ; i < idx; i += ){
int u = edge[i].u, v = edge[i].v;
if( vis[u] && !vis[v] && (edge[i].f == ) )
res[cnt++] = i;
}
printf("%d\n", cnt );
for(int i = ; i < cnt; i++ ){
int u = edge[ res[i] ].u, v = edge[ res[i] ].v;
if( u == S ) printf("%d -\n", v);
else printf("%d +\n", u-n );
}
} int main(){
while( scanf("%d%d",&n,&m) != EOF ){
S = , T = *n+, N = *n+; idx = ;
memset( head, -, sizeof(head)); for(int i = ; i <= n; i++ )
scanf("%d", &A[i]);
for(int i = ; i <= n; i++ )
scanf("%d", &B[i]);
int a, b;
for(int i = ; i < m; i++ ){
scanf("%d%d", &a,&b);
AddEdge( a, n+b, inf );
}
for(int i = ; i <= n; i++){
AddEdge( S, i, B[i] ); // - out
AddEdge( n+i, T, A[i] );// + in
}
solve();
}
return ;
}

poj 2125 Destroying The Graph 最小割+方案输出的更多相关文章

  1. POJ 2125 Destroying The Graph [最小割 打印方案]

    Destroying The Graph Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8311   Accepted: 2 ...

  2. POJ - 2125 Destroying The Graph (最小点权覆盖)

    题意:给一张图,现在要删去所有的边,删去一个点的所有入边和所有出边都有其对应\(W_{i+}\)和\(W_{i-}\).求删去该图的最小花费,并输出解 分析:简而言之就是用最小权值的点集去覆盖所有的边 ...

  3. POJ 2125 Destroying The Graph (二分图最小点权覆盖集+输出最小割方案)

    题意 有一个图, 两种操作,一种是删除某点的所有出边,一种是删除某点的所有入边,各个点的不同操作分别有一个花费,现在我们想把这个图的边都删除掉,需要的最小花费是多少. 思路 很明显的二分图最小点权覆盖 ...

  4. poj 2125 Destroying The Graph (最小点权覆盖)

    Destroying The Graph http://poj.org/problem?id=2125 Time Limit: 2000MS   Memory Limit: 65536K       ...

  5. POJ 2125 Destroying the Graph 二分图最小点权覆盖

    Destroying The Graph Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8198   Accepted: 2 ...

  6. 图论(网络流,二分图最小点权覆盖):POJ 2125 Destroying The Graph

    Destroying The Graph   Description Alice and Bob play the following game. First, Alice draws some di ...

  7. POJ 2125 Destroying The Graph 二分图 最小点权覆盖

    POJ2125 题意简述:给定一个有向图,要通过某些操作删除所有的边,每一次操作可以选择任意一个节点删除由其出发的所有边或者通向它的所有边,两个方向有不同的权值.问最小权值和的解决方案,要输出操作. ...

  8. ●POJ 2125 Destroying The Graph

    题链: http://poj.org/problem?id=2125 题解: 最小割 + 输出割方案.建图:拆点,每个题拆为 i 和 i'分别表示其的入点和出点建立超源 S和超汇 T.S -> ...

  9. poj 3469 Dual Core CPU——最小割

    题目:http://poj.org/problem?id=3469 最小割裸题. 那个限制就是在 i.j 之间连双向边. 根据本题能引出网络流中二元关系的种种. 别忘了写 if ( x==n+1 ) ...

随机推荐

  1. Linux less 常用导航命令

    linux中经常用less来查看文件,文件较短的时候用pgup(pageup), pgdn(pagedown),↑,↓几个键够,但是当文件比较长的时候用一些快捷键就能很方便实现快速导航. 1. 按匹配 ...

  2. GoogLeNet解读

    转载:http://blog.csdn.net/shuzfan/article/details/50738394 GoogLeNet主要贡献提出了Inception结构: Architectural ...

  3. ASCII码与16进制的互相转换(表)

    所谓的ASCII和16进制都只是概念上的东西,在计算机中通通是二进制 转换应该是输出的转换,同样是一个数,在计算机内存中表示是一样的,只是输出不一样ASCII是针对字符的编码,几乎是键盘上的字符的编码 ...

  4. 高可用(HA)架构

    http://aokunsang.iteye.com/blog/2053719   浅谈web应用的负载均衡.集群.高可用(HA)解决方案 http://zhuanlan.51cto.com/art/ ...

  5. Go之单元测试

    go单元测试需要按照gotest的规范来编写: 1.文件名必须以xx_test.go命名 2.方法必须是Test[^a-z]开头 3.方法参数必须 t *testing.T   在运行gotest的时 ...

  6. mysql报错“Starting MySQL...The server quit without updating PID file”处理

    http://blog.csdn.net/lzq123_1/article/details/51354179 注意:要将/usr/bin/mysql_install_db替换成 /usr/bin/my ...

  7. HTML 引用

    关于 HTML 引用: (1) <q> 和 <blockquote> 用于实现长短不一的引用语(2) <q> 用于短的引用,<blockquote> 用 ...

  8. 嵌入式ROOTFS transplantation

    作一个嵌入式Linux rootfs,并且实现 web 服务 1. 文件系统简介 •理论上说一个嵌入式设备如果内核能够运行起来,且不需要运行用户进程的话,是不需要文件系统的,文件系统简单的说就是一种目 ...

  9. React Native(十三)——ios键盘挡住textInput

    渐入佳境 用React Native重构的项目也快接近尾声,剩下的就是适配ios的功能了.慢慢地也从中琢磨出了一点门道,于是就遇见了键盘遮挡textInput问题斑斑: 正常页面: android点击 ...

  10. 《Lua程序设计》第4章 语句 学习笔记

    Lua中的常规语句包括:赋值.控制结构和过程调用.Lua还支持一些不太常见的语句,如:多重赋值(multiple assignment) 和 局部变量声明.4.1 赋值Lua允许“多重赋值”,也就是一 ...