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 ...
随机推荐
- [并查集] 1107. Social Clusters (30)
1107. Social Clusters (30) When register on a social network, you are always asked to specify your h ...
- 51单片机数组的定义方法(code与data的作用)
转自:http://blog.sina.com.cn/s/blog_94994f7b01010s1h.html 数组前不加“code”或“data”,则默认将数组存放在程序存储器中:code 指定数据 ...
- Alpha阶段敏捷冲刺⑥
1.提供当天站立式会议照片一张. 每个人的工作 (有work item 的ID),并将其记录在码云项目管理中: 昨天已完成的工作. 实现对账单条目的编辑 初步设计设置页面 今天要完成的工作. 账单明细 ...
- cxDBVerticalGrid
定位在第一行并显示内置编辑器 cxDBVerticalGrid1.FocusedRow := cxDBVerticalGrid1.Rows[0]; cxDBVerticalGrid1.ShowEdit ...
- Jaxb2实现JavaBean与xml互转的方法详解
本文实例讲述了Jaxb2实现JavaBean与xml互转的方法.分享给大家供大家参考,具体如下: 一.简介 JAXB(Java Architecture for XML Binding) 是一个业界的 ...
- SQLSERVER 修改实例名以及架构信息
1. GUI的方式 后者是 alter database 的方式修改 instance的名字 2. 在全局的安全性下面创建用户. 3. 在实例的安全性下面创建架构和用户(架构名与用户名一直, 使用新实 ...
- Java并发编程之线程安全、线程通信
Java多线程开发中最重要的一点就是线程安全的实现了.所谓Java线程安全,可以简单理解为当多个线程访问同一个共享资源时产生的数据不一致问题.为此,Java提供了一系列方法来解决线程安全问题. syn ...
- mysql 读写锁
1. 表读锁 lock table tablename read; 例如: 从上图中可以看到,当给表a加了读锁之后,该进程本身对表a是可读的,但是不可写,再看在另外一个进程中: 在另外一个进程中表a也 ...
- iphonex适配
这一篇具体适配步骤比较全面 iphonex适配 这一篇图文讲解比较全面 关于H5页面在iPhoneX适配
- matlab dist函数
dist——欧式距离加权函数(Euclidean distance weight function) 语法: Z = dist(W,P) df = dist('deriv') D = di ...