poj 2125 Destroying The Graph (最小点权覆盖)
| Time Limit: 2000MS | Memory Limit: 65536K | |||
Description
Alice assigns two costs to each vertex: Wi+ and Wi-. If Bob removes all arcs incoming into the i-th vertex he pays Wi+ dollars to Alice, and if he removes outgoing arcs he pays Wi- dollars.
Find out what minimal sum Bob needs to remove all arcs from the graph.
Input
Output
Sample Input
3 6
1 2 3
4 2 1
1 2
1 1
3 2
1 2
3 1
2 3
Sample Output
5
3
1 +
2 -
2 +
题目大意:
n个点m条边的有向图
需要移走这张图里所有的边
每次可以选择移走点i的所有入边或所有出边
每步操作都有对应的代价
求最小代价移走所有的边
注:边有自环和平行边 最小点权覆盖集
=最小割
拆点
源点向每个点连一条流量为outgoing pay的边
每个点向汇点连一条流量为incoming pay的边
原图中的边i,j,由i向拆出的j连inf边
跑最小割
方案的输出:
从源点遍历残量网络,边还有流量就遍历,记录所有遍历到的点
原本就有的点,如果没有被遍历到,就说明它被割了
拆出的点,如果被遍历到,说明它被割了
#include<cstdio>
#include<queue>
using namespace std;
int n,m,tot=,ans;
int front[],to[],nextt[],cap[];
int lev[],cur[];
int src,decc;
bool g[];
queue<int>q;
void add(int u,int v,int w)
{
to[++tot]=v;nextt[tot]=front[u];front[u]=tot;cap[tot]=w;
to[++tot]=u;nextt[tot]=front[v];front[v]=tot;cap[tot]=;
}
bool bfs()
{
for(int i=;i<=decc;i++) {lev[i]=-;cur[i]=front[i];}
while(!q.empty()) q.pop();
q.push(src);lev[src]=;
while(!q.empty())
{
int now=q.front();q.pop();
for(int i=front[now];i;i=nextt[i])
{
int t=to[i];
if(cap[i]>&&lev[t]==-)
{
lev[t]=lev[now]+;
q.push(t);
if(t==decc) return true;
}
}
}
return false;
}
int dinic(int now,int flow)
{
if(now==decc) return flow;
int rest=,delta;
for(int & i=cur[now];i;i=nextt[i])
{
int t=to[i];
if(lev[t]>lev[now]&&cap[i]>)
{
delta=dinic(t,min(flow-rest,cap[i]));
if(delta)
{
cap[i]-=delta;cap[i^]+=delta;
rest+=delta;if(rest==flow) break;
}
}
}
if(rest!=flow) lev[now]=-;
return rest;
}
void cut(int now)
{
g[now]=true;
for(int i=front[now];i;i=nextt[i])
{
if(cap[i]==||g[to[i]]) continue;
cut(to[i]);
}
}
int main()
{
scanf("%d%d",&n,&m);
decc=n+<<;
int x,y;
for(int i=;i<=n;i++)
{
scanf("%d",&x);
add(i<<|,decc,x);
}
for(int i=;i<=n;i++)
{
scanf("%d",&x);
add(src,i<<,x);
}
for(int i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
add(x<<,y<<|,2e9);
}
while(bfs()) ans+=dinic(src,2e9);
printf("%d\n",ans);
int sum=;
cut(src);
for(int i=;i<=n;i++)
{
if(g[i<<|]) sum++;
if(!g[i<<]) sum++;
}
printf("%d\n",sum);
for(int i=;i<=n;i++)
{
if(!g[i<<]) printf("%d -\n",i);
if(g[i<<|]) printf("%d +\n",i); }
}
错误:
1、
应该是
源点向每个点连一条流量为outgoing pay的边
每个点向汇点连一条流量为incoming pay的边
连反了
与源点相连的点,连出去的边是点打出的,所以源点与点之间的边控制的是出边的流量
汇点同理
2、方案输出方法错误
错误方法:
在残量网络中,如果与源点相连的边流量为0,说明这个点被割了
如果汇点连出去的边的流量 为这条边指 向的点的原流量,说明这个点被割了
前半部分是正确的,但后半部分是错的
因为跑最大流过程中,增光路上所有边流量都减,
比如有一条边由1指向2,所有花费都是1
跑完最大流后,源点——1 残量为0
2——汇点 残量为0
最终判断的是割掉2个点,但实际割其中一个就行
/*for(int i=front[src];i;i=nextt[i])
{
if(cap[i]==0)
{
sum++;
a[sum][0]=to[i]/2;a[sum][1]='+';
}
}
for(int i=front[decc];i;i=nextt[i])
{
if(cap[i]==out[to[i]/2])
{
sum++;
a[sum][0]=to[i]/2;a[sum][1]='-';
}
}*/
错误代码
3、题目中说有自环,做的时候把它特判去掉了,错
poj 2125 Destroying The Graph (最小点权覆盖)的更多相关文章
- POJ - 2125 Destroying The Graph (最小点权覆盖)
题意:给一张图,现在要删去所有的边,删去一个点的所有入边和所有出边都有其对应\(W_{i+}\)和\(W_{i-}\).求删去该图的最小花费,并输出解 分析:简而言之就是用最小权值的点集去覆盖所有的边 ...
- POJ2125 Destroying The Graph (最小点权覆盖集)(网络流最小割)
Destroying The Graph Time Limit: 2000MS Memo ...
- POJ 2125 Destroying The Graph [最小割 打印方案]
Destroying The Graph Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8311 Accepted: 2 ...
- poj 2125 Destroying The Graph 最小割+方案输出
构图思路: 1.将所有顶点v拆成两个点, v1,v2 2.源点S与v1连边,容量为 W- 3.v2与汇点连边,容量为 W+ 4.对图中原边( a, b ), 连边 (a1,b2),容量为正无穷大 则该 ...
- POJ 2125 Destroying the Graph 二分图最小点权覆盖
Destroying The Graph Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8198 Accepted: 2 ...
- POJ 2125 Destroying The Graph (二分图最小点权覆盖集+输出最小割方案)
题意 有一个图, 两种操作,一种是删除某点的所有出边,一种是删除某点的所有入边,各个点的不同操作分别有一个花费,现在我们想把这个图的边都删除掉,需要的最小花费是多少. 思路 很明显的二分图最小点权覆盖 ...
- POJ 2125 Destroying The Graph 二分图 最小点权覆盖
POJ2125 题意简述:给定一个有向图,要通过某些操作删除所有的边,每一次操作可以选择任意一个节点删除由其出发的所有边或者通向它的所有边,两个方向有不同的权值.问最小权值和的解决方案,要输出操作. ...
- POJ 3308 Paratroopers (对数转换+最小点权覆盖)
题意 敌人侵略r*c的地图.为了消灭敌人,可以在某一行或者某一列安置超级大炮.每一个大炮可以瞬间消灭这一行(或者列)的敌人.安装消灭第i行的大炮消费是ri.安装消灭第j行的大炮消费是ci现在有n个敌人 ...
- poj 3308 Paratroopers(二分图最小点权覆盖)
Paratroopers Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8954 Accepted: 2702 Desc ...
随机推荐
- gdb调试器学习链接
首先要带 -g 选项用gcc编译 常用指令:http://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/gdb.html#gdb 带main的命令行参 ...
- 结对&团队之1715|K班取经
声明:同学请勿抄袭,追责莫要怪我: 因为暂时闲着没事,就翻阅学长学姐的博客找找灵感,个人觉得应该还有人和我一样对软工实践未来的一大段路还很天真,包括目前的结对作业和团队组队也很迷路,于是写下这篇博客提 ...
- 09_Java面向对象_第9天(类、封装)_讲义
今日内容介绍 1.面向对象思想 2.类与对象的关系 3.局部变量和成员变量的关系 4.封装思想 5.private,this关键字 6.随机点名器 01面向对象和面向过程的思想 A: 面向过程与面向对 ...
- sprintf函数 %6.2f
%6.2f6表示数据表示至少6位,后面的.2表示小数点后保留两位 比如2342.123415用这个表示的话,结果就是2342.12如果不足六位就会在前面补空格超过六位的话正常显示 代码例子:int m ...
- 2D变换
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Tween.js 动画效果
一.apply,和call的用法. 先来一个与本次博文无关的东西,就是apply和call的用法.其实apply和call的用法都一样,只是他们的传参不一样.apply是数组,而call是单独的传,类 ...
- python自动化之正则
import re phoneNumRegex=re.compile(r'\d\d\d-\d\d\d-\d\d\d\d') mo=phoneNumRegex.search('My number is ...
- GIT的使用方法
GIT的使用方法 1.电脑首先安装GIT, 2.在官网注册GitHub账号. 一,使用git在控制台进行本地操作 1.打开GitBash 2.填写用户名和邮箱作为标识分别执行以下命令: git/ co ...
- mysql二进制日志的开启和使用
二进制日志(BINLOG)记录了所有的ddl和dml语句,但不包括数据查询语句.语句以“事件”的形式保存,描述数据更改过程. 环境:win8 mysql5.6.23 1.mysql开启二进制日志 ...
- Barricade HDU - 5889(最短路+最小割)
Barricade Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total S ...