构图思路:

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. 如何让form表单在enter键入时不提交

    今天在做我的一个小玩意 在线聊天工具的时候 form表单只有一个text和一个button每当我键入enter的时候就刷新.很是郁闷,直接在form上onsumbit=false.才行. 下面是我查询 ...

  2. 更好的使用JAVA线程池

    这篇文章分别从线程池大小参数的设置.工作线程的创建.空闲线程的回收.阻塞队列的使用.任务拒绝策略.线程池Hook等方面来了解线程池的使用,其中涉及到一些细节包括不同参数.不同队列.不同拒绝策略的选择. ...

  3. 安装MySQL-python: EnvironmentError:mysql config not found

    1执行 sudo yum install python-devel 2 find / -name mysql_config 在/usr/bin/下发现了这个文件 3. 后修改MySQL-python- ...

  4. [OpenCV] Image Processing - Grayscale Transform & Histogram

    颜色直方图 首先,先介绍一些Hist的基本使用. Ref:[OpenCV]数字图像灰度直方图 官方文档:https://docs.opencv.org/trunk/d8/dbc/tutorial_hi ...

  5. EditDistance,求两个字符串最小编辑距离,动态规划

    问题描述: 题目描述Edit DistanceGiven two words word1 and word2, find the minimum number of steps required to ...

  6. Eclipse------使用Maven install出错:编码GBK的不可映射字符

    使用Maven install时报错:编码GBK的不可映射字符 原因:Maven默认使用GBK进行编码 解决方法: 在pom.xml文件中添加如下代码即可 <project> <pr ...

  7. Java实现经理与员工的差异

    对于在同一家公司工作的经历和员工而言,两者是有很多共同点的.例如,每个月都要发工资,但是经理在完成目标任务后,还会获得奖金.此时,利用员工类来编写经理类就会少写很多代码,利用继承技术可以让经理类使用员 ...

  8. Go之简单并发

    func Calculate(id int) { fmt.Println(id) } 使用go来实现并发 func main() { for i := 0; i < 100; i++ { go ...

  9. X-WAF简单测试体验

    X-WAF 最近才关注到的一款云WAF,花了一些时间搭建了一个环境,并做了一些测试,感觉比较适合新手来练习WAF Bypass. X-WAF是一款适用中.小企业的云WAF系统,让中.小企业也可以非常方 ...

  10. React Native(四)——顶部以及底部导航栏实现方式

    效果图: 一步一步慢慢来: 其实刚入手做app的时候,就应该做出简单的顶部以及底部导航栏.无奈又在忙其他事情,导致这些现在才整理出来. 1.顶部导航栏:react-native-scrollable- ...