POJ 2125 Destroying The Graph (二分图最小点权覆盖集+输出最小割方案)
题意
有一个图, 两种操作,一种是删除某点的所有出边,一种是删除某点的所有入边,各个点的不同操作分别有一个花费,现在我们想把这个图的边都删除掉,需要的最小花费是多少。
思路
很明显的二分图最小点权覆盖集。WA在输出最小割方案上。
【输出最小割方案】从源点S做一次DFS遍历,标记所有访问到的点,这些点就是S点集。然后对于每一条满流边,如果其两端点一个在S点集一个不在则该边就是此方案下的最小割边。
代码
[cpp]
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <string>
#include <cstring>
#define MID(x,y) ((x+y)/2)
#define MEM(a,b) memset(a,b,sizeof(a))
#define REP(i, begin, m) for (int i = begin; i < begin+m; i ++)
using namespace std;
const int MAXV = 205;
const int MAXE = 10005;
const int oo = 0x3fffffff;
template <typename T>
struct Dinic{
struct flow_node{
int u, v;
T flow;
int opp;
int next;
}arc[2*MAXE];
int vn, en, head[MAXV];
int cur[MAXV];
int q[MAXV];
int path[2*MAXE], top;
int dep[MAXV];
void init(int n){
vn = n;
en = 0;
MEM(head, -1);
}
void insert_flow(int u, int v, T flow){
arc[en].u = u;
arc[en].v = v;
arc[en].flow = flow;
arc[en].next = head[u];
head[u] = en ++;
arc[en].u = v;
arc[en].v = u;
arc[en].flow = 0;
arc[en].next = head[v];
head[v] = en ++;
}
bool bfs(int s, int t){
MEM(dep, -1);
int lq = 0, rq = 1;
dep[s] = 0;
q[lq] = s;
while(lq < rq){
int u = q[lq ++];
if (u == t){
return true;
}
for (int i = head[u]; i != -1; i = arc[i].next){
int v = arc[i].v;
if (dep[v] == -1 && arc[i].flow > 0){
dep[v] = dep[u] + 1;
q[rq ++] = v;
}
}
}
return false;
}
T solve(int s, int t){
T maxflow = 0;
while(bfs(s, t)){
int i, j;
for (i = 1; i <= vn; i ++) cur[i] = head[i];
for (i = s, top = 0;;){
if (i == t){
int mink;
T minflow = 0x7fffffff; //要比容量的oo大
for (int k = 0; k < top; k ++)
if (minflow > arc[path[k]].flow){
minflow = arc[path[k]].flow;
mink = k;
}
for (int k = 0; k < top; k ++)
arc[path[k]].flow -= minflow, arc[path[k]^1].flow += minflow;
maxflow += minflow;
top = mink;
i = arc[path[top]].u;
}
for (j = cur[i]; j != -1; cur[i] = j = arc[j].next){
int v = arc[j].v;
if (arc[j].flow && dep[v] == dep[i] + 1)
break;
}
if (j != -1){
path[top ++] = j;
i = arc[j].v;
}
else{
if (top == 0) break;
dep[i] = -1;
i = arc[path[-- top]].u;
}
}
}
return maxflow;
}
};
Dinic <int> dinic;
vector <pair<int, char> > res;
bool vis[MAXV];
void dfs(int u){
vis[u] = true;
for (int i = dinic.head[u]; i != -1; i = dinic.arc[i].next){
if (dinic.arc[i].flow <= 0) continue;
int v = dinic.arc[i].v;
if (!vis[v]){
dfs(v);
}
}
}
int main(){
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
int n, m;
while(scanf("%d %d", &n, &m) != EOF){
dinic.init(2*n+2);
REP(i, 1, n){
int tmp;
scanf("%d", &tmp);
dinic.insert_flow(i+n, 2*n+2, tmp);
}
REP(i, 1, n){
int tmp;
scanf("%d", &tmp);
dinic.insert_flow(2*n+1, i, tmp);
}
REP(i, 1, m){
int u, v;
scanf("%d %d", &u, &v);
dinic.insert_flow(u, v+n, oo);
}
printf("%d\n", dinic.solve(2*n+1, 2*n+2));
res.clear();
MEM(vis, 0);
dfs(2*n+1);
for (int i = 0; i < dinic.en; i ++){
if (dinic.arc[i].u == 2*n+1 && dinic.arc[i].flow == 0){
if (!vis[dinic.arc[i].v])
res.push_back(make_pair(dinic.arc[i].v, '-'));
}
if (dinic.arc[i].v == 2*n+2 && dinic.arc[i].flow == 0){
if (vis[dinic.arc[i].u])
res.push_back(make_pair(dinic.arc[i].u - n, '+'));
}
}
printf("%d\n", (int)res.size());
for (int i = 0; i < (int)res.size(); i ++){
printf("%d %c\n", res[i].first, res[i].second);
}
}
return 0;
}
[/cpp]
POJ 2125 Destroying The Graph (二分图最小点权覆盖集+输出最小割方案)的更多相关文章
- POJ 2125 Destroying the Graph 二分图最小点权覆盖
Destroying The Graph Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8198 Accepted: 2 ...
- POJ 2125 Destroying The Graph 二分图 最小点权覆盖
POJ2125 题意简述:给定一个有向图,要通过某些操作删除所有的边,每一次操作可以选择任意一个节点删除由其出发的所有边或者通向它的所有边,两个方向有不同的权值.问最小权值和的解决方案,要输出操作. ...
- POJ2125 Destroying The Graph (最小点权覆盖集)(网络流最小割)
Destroying The Graph Time Limit: 2000MS Memo ...
- poj 2125 Destroying The Graph (最小点权覆盖)
Destroying The Graph http://poj.org/problem?id=2125 Time Limit: 2000MS Memory Limit: 65536K ...
- POJ - 2125 Destroying The Graph (最小点权覆盖)
题意:给一张图,现在要删去所有的边,删去一个点的所有入边和所有出边都有其对应\(W_{i+}\)和\(W_{i-}\).求删去该图的最小花费,并输出解 分析:简而言之就是用最小权值的点集去覆盖所有的边 ...
- POJ2125 Destroying The Graph(二分图最小点权覆盖集)
最小点权覆盖就是,对于有点权的有向图,选出权值和最少的点的集合覆盖所有的边. 解二分图最小点权覆盖集可以用最小割: vs-X-Y-vt这样连边,vs和X部点的连边容量为X部点的权值,Y部和vt连边容量 ...
- POJ 2125 最小点权覆盖集(输出方案)
题意:给一个图(有自回路,重边),要去掉所有边,规则:对某个点,可以有2种操作:去掉进入该点 的所有边,也可以去掉出该点所有边,(第一种代价为w+,第二种代价为w-).求最小代价去除所有边. 己思:点 ...
- 最小点权覆盖集&最大点权独立集
最小点权覆盖集 二分图最小点权覆盖集解决的是这样一个问题: 在二分图中,对于每条边,两个端点至少选一个,求所选取的点最小权值和. 方法: 1.先对图二分染色,对于每条边两端点的颜色不同 2.然后建立源 ...
- hdu1569 方格取数(2) 最大点权独立集=总权和-最小点权覆盖集 (最小点权覆盖集=最小割=最大流)
/** 转自:http://blog.csdn.net/u011498819/article/details/20772147 题目:hdu1569 方格取数(2) 链接:https://vjudge ...
随机推荐
- POJ 3185
The Water Bowls Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4088 Accepted: 1609 D ...
- DF学Mysql(二)——数据表的基本操作
1.创建数据表 先使用“USE <数据库名>”指定在哪个数据库中操作 CREATE TABLE <表名> ( 字段1 数据类型 [列级别约束条件] [默认值], 字段2 数据类 ...
- UVA 10943 How do you add? DP
Larry is very bad at math — he usually uses a calculator, whichworked well throughout college. Unfor ...
- BZOJ 4199 品酒大会
以前一直听说什么后缀数组height合并之类的 表示我这种后缀数组都敲不熟的蒟蒻怎么会写 但是做了做觉得还是很简单的嘛 这个题是有两问的,第一问是求LCP>=R的后缀对有多少个 这个就是AHOI ...
- ByteArrayInputStream与ByteArrayOutputStrean的使用
String str="sdfasdfasdfa加减法爱的色放就阿克苏地方啊"; InputStream is=new ByteArrayInputStream(str.toStr ...
- iOS开发--线程通信
线程间的通信主要用于主线程与子线程的,也有用于子线程与子线程的 介绍下面几种通信方式 1.利用GCD方式(推荐) - (void)touchesBegan:(NSSet<UITouch *> ...
- Ubuntu rsync同步
>服务器端:Ubuntu 9.10 - 192.168.1.3客户端:Ubuntu 10.04 - 192.168.1.73 我们先来设置一下服务器端的配置 1.ubuntu系统安装完之后,rs ...
- Sql server cast(as nvarchar) 默认长度问题
Sql server 在我的SQL语句中:sql=".........cast(ziduan as nvarchar) ..............." 这样之后,ziduan被转 ...
- chrome开发配置(一)安装配置工具
1.下载depot_tools,解压到本地,然后将解压后的depot_tools根目录添加到path环境变量: depot_tools下载地址 2.cmd 运行gclient,git比较大,有100M ...
- JSP页面的构成
JSP页面就是带有JSP元素的常规Web页面,它由静态内容和动态内容构成.其中,静态内容指HTML元素,动态内容(JSP元素)包括指令元素.脚本元素.动作元素.注释等内容. 1.指令元素 指令 ...