POJ 2125 Destroying the Graph 二分图最小点权覆盖
| Time Limit: 2000MS | Memory Limit: 65536K | |||
| Total Submissions: 8198 | Accepted: 2635 | Special Judge | ||
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 +
Source
【题意】:
N个点M条边的有向图,给出如下两种操作。
删除点i的所有出边,代价是Ai。
删除点j的所有入边,代价是Bj。
求最后删除图中所有的边的最小代价。
其实就是二分图最小点权覆盖。
定义:从x或者y集合中选取一些点,使这些点覆盖所有的边,并且选出来的点的权值尽可能小。
//最小点权覆盖就是求最小割(证明可参考胡伯涛论文“最小割模型在信息学竞赛中的应用”)。
【题解】:
拆点。n个点拆成2n个点(左右各n个,i与(i+n)对应,之间连容量INF的边),S和i连容量为Ai的边,(i+n)与T之间连容量为Bi的边,求最小割即可
这样做为什么对呢?
当一条边存在的条件就是网络中还存在从S到T的非满流边!
方案输出不多说。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define R register
#define inf 0x3f3f3f3f
using namespace std;
int read(){
R int x=;bool f=;
R char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=;ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return f?x:-x;
}
const int N=1e5+;
struct node{
int v,next,cap,flow;
}e[N<<];int tot=;
struct data{
int x,op,val;
bool operator <(const data &a)const{
return val==a.val?x<a.x:val<a.val;
}
}record[N];
int n,m,cs,cc,S,T,a[N],b[N],cur[N],head[N],dis[N],q[N*];
bool mark[N];
void add(int x,int y,int z){
e[++tot].v=y;e[tot].next=head[x];e[tot].cap=z;e[tot].flow=;head[x]=tot;
e[++tot].v=x;e[tot].next=head[y];e[tot].cap=;e[tot].flow=;head[y]=tot;
}
bool bfs(){
int h=,t=;
memset(dis,-,sizeof(dis));
dis[S]=;q[]=S;
while(h!=t){
int x=q[++h];
for(int i=head[x];i;i=e[i].next){
int v=e[i].v;
if(dis[v]==-&&e[i].cap>e[i].flow){
dis[v]=dis[x]+;
q[++t]=v;
}
}
}
return dis[T]!=-;
}
int dfs(int x,int f){
if(x==T||!f) return f;
int used=,f1;
for(int &i=cur[x];i;i=e[i].next){
if(dis[x]+==dis[e[i].v]&&(f1=dfs(e[i].v,min(f,e[i].cap-e[i].flow)))>){
e[i].flow+=f1;e[i^].flow-=f1;
used+=f1;f-=f1;
if(!f) break;
}
}
return used;
}
int dinic(){
int ans=;
while(bfs()){
for(int i=S;i<=T;i++) cur[i]=head[i];
ans+=dfs(S,0x7fffffff);
}
return ans;
}
void dfs_cut(int x){
if(x==T) return ;
mark[x]=;
for(int i=head[x];i;i=e[i].next){
int v=e[i].v,val,op;
if(!mark[v]){
if(e[i].cap==e[i].flow){
if(x!=S){
if(x>n) op=,val=b[x-n];
else op=,val=a[x];
record[++cc].x=x;record[cc].op=op;record[cc].val=val;
}
if(v!=T){
if(v>n) op=,val=b[v-n];
else op=,val=a[v];
record[++cc].x=v;record[cc].op=op;record[cc].val=val;
}
}
dfs_cut(v);
} }
}
int main(){
n=read();m=read();
S=;T=n<<|;
for(int i=;i<=n;i++) a[i]=read(),add(S,i,a[i]);
for(int i=;i<=n;i++) b[i]=read(),add(i+n,T,b[i]);
for(int i=,x,y;i<=m;i++) x=read(),y=read(),add(x,y+n,inf);
printf("%d\n",dinic());
dfs_cut(S);
for(int i=;i<=n;i++){
if(!mark[i]) cs++;
if(mark[i+n]) cs++;
}
printf("%d\n",cs);
for(int i=;i<=cc;i++) if(record[i].x>n) record[i].x-=n;
sort(record+,record+cc+);
for(int i=;i<=cs;i++){
int &x=record[i].x,&y=record[i].op;
printf("%d ",x);putchar(y?'+':'-');printf("\n");
}
return ;
}
输出方案WA到挺的代码
//AC代码(终于改出来了)
#include<cstdio>
#include<iostream>
using namespace std;
int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const int N=1e5+;
const int inf=0x7fffffff;
struct node{
int v,next,cap;
}e[N*];int tot=;
int n,m,p,S,T,a[N],b[N],head[N],dis[N],q[N*];
bool vis[N];
void add(int x,int y,int z){
e[++tot].v=y;e[tot].cap=z;e[tot].next=head[x];head[x]=tot;
e[++tot].v=x;e[tot].cap=;e[tot].next=head[y];head[y]=tot;
}
bool bfs(){
for(int i=S;i<=T;i++) dis[i]=inf;
int h=,t=;q[t]=S;dis[S]=;
while(h!=t){
int x=q[++h];
for(int i=head[x],v;i;i=e[i].next){
if(e[i].cap&&dis[v=e[i].v]>dis[x]+){
dis[v]=dis[x]+;
if(v==T) return ;
q[++t]=v;
}
}
}
return ;
}
int dfs(int x,int f){
if(x==T) return f;
int used=,t;
for(int i=head[x],v;i;i=e[i].next){
if(e[i].cap&&dis[v=e[i].v]==dis[x]+){
t=dfs(v,min(f,e[i].cap));
e[i].cap-=t;e[i^].cap+=t;
used+=t;f-=t;
if(!f) return used;
}
}
if(!used) dis[x]=;
return used;
}
int dinic(){
int res=;
while(bfs()) res+=dfs(S,inf);
return res;
}
void dfs_cut(int x){
vis[x]=;
for(int i=head[x],v;i;i=e[i].next){
if(!e[i].cap||vis[v=e[i].v]) continue;
dfs_cut(v);
}
}
int main(){
n=read();m=read();S=;T=n<<|;
for(int i=;i<=n;i++) a[i]=read(),add(i+n,T,a[i]);
for(int i=;i<=n;i++) b[i]=read(),add(S,i,b[i]);//边是反的,dfs_cut是正的。WA*1
for(int i=,x,y;i<=m;i++) x=read(),y=read(),add(x,y+n,inf);
printf("%d\n",dinic());
dfs_cut(S);
for(int i=;i<=n;i++){
if(!vis[i]) p++;
if(vis[i+n]) p++;
}
printf("%d\n",p);
for(int i=;i<=n;i++){
if(!vis[i]) printf("%d -\n",i);
if(vis[i+n]) printf("%d +\n",i);
}
return ;
}
POJ 2125 Destroying the Graph 二分图最小点权覆盖的更多相关文章
- POJ 2125 Destroying The Graph (二分图最小点权覆盖集+输出最小割方案)
题意 有一个图, 两种操作,一种是删除某点的所有出边,一种是删除某点的所有入边,各个点的不同操作分别有一个花费,现在我们想把这个图的边都删除掉,需要的最小花费是多少. 思路 很明显的二分图最小点权覆盖 ...
- POJ 2125 Destroying The Graph 二分图 最小点权覆盖
POJ2125 题意简述:给定一个有向图,要通过某些操作删除所有的边,每一次操作可以选择任意一个节点删除由其出发的所有边或者通向它的所有边,两个方向有不同的权值.问最小权值和的解决方案,要输出操作. ...
- poj 2125 Destroying The Graph (最小点权覆盖)
Destroying The Graph http://poj.org/problem?id=2125 Time Limit: 2000MS Memory Limit: 65536K ...
- POJ2125 Destroying The Graph 二分图 + 最小点权覆盖 + 最小割
思路来源:http://blog.csdn.net/lenleaves/article/details/7873441 求最小点权覆盖,同样求一个最小割,但是要求出割去了那些边, 只要用最终的剩余网络 ...
- POJ2125 Destroying The Graph(二分图最小点权覆盖集)
最小点权覆盖就是,对于有点权的有向图,选出权值和最少的点的集合覆盖所有的边. 解二分图最小点权覆盖集可以用最小割: vs-X-Y-vt这样连边,vs和X部点的连边容量为X部点的权值,Y部和vt连边容量 ...
- POJ - 2125 Destroying The Graph (最小点权覆盖)
题意:给一张图,现在要删去所有的边,删去一个点的所有入边和所有出边都有其对应\(W_{i+}\)和\(W_{i-}\).求删去该图的最小花费,并输出解 分析:简而言之就是用最小权值的点集去覆盖所有的边 ...
- poj 3308 Paratroopers(二分图最小点权覆盖)
Paratroopers Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8954 Accepted: 2702 Desc ...
- POJ3308 Paratroopers(最小割/二分图最小点权覆盖)
把入侵者看作边,每一行每一列都是点,选取某一行某一列都有费用,这样问题就是选总权最小的点集覆盖所有边,就是最小点权覆盖. 此外,题目的总花费是所有费用的乘积,这时有个技巧,就是取对数,把乘法变为加法运 ...
- POJ 3308 Paratroopers(最大流最小割の最小点权覆盖)
Description It is year 2500 A.D. and there is a terrible war between the forces of the Earth and the ...
随机推荐
- spring boot(五):spring data jpa的使用
在上篇文章springboot(二):web综合开发中简单介绍了一下spring data jpa的基础性使用,这篇文章将更加全面的介绍spring data jpa 常见用法以及注意事项 使用spr ...
- 【Python五篇慢慢弹(3)】函数修行知python
函数修行知python 作者:白宁超 2016年10月9日21:51:52 摘要:继<快速上手学python>一文之后,笔者又将python官方文档认真学习下.官方给出的pythondoc ...
- word2vec 中的数学原理详解
word2vec 是 Google 于 2013 年开源推出的一个用于获取 word vector 的工具包,它简单.高效,因此引起了很多人的关注.由于 word2vec 的作者 Tomas Miko ...
- 原创:去繁存简,回归本源:微信小程序公开课信息分析《一》
以前我开过一些帖子,我们内部也做过一些讨论,我们从张小龙的碎屏图中 ,发现了重要讯息: 1:微信支付将成为重要场景: 2:这些应用与春节关系不小,很多应用在春节时,有重要的场景开启可能性: 3:春节是 ...
- Java进击C#——语法之多线程
本章简言 上一章中笔者对C#一些独有的语法点进行讲解,相信也可以看C#的一些神奇之处.那么本章主要是放在多线程这方面的知识.不管是C#还是JAVA在开发过程或多或少都会用到关于多线程的编程.当然笔者不 ...
- 通过NPOI操作Excel
最近在做的一个项目中需要生成Excel,通过学习使用NPOI实现了相关需求,写了一个简便操作的类,记录如下: public class NPOIHelperForExcel { #region exc ...
- 分享api接口验证模块
一.前言 权限验证在开发中是经常遇到的,通常也是封装好的模块,如果我们是使用者,通常指需要一个标记特性或者配置一下就可以完成,但实际里面还是有许多东西值得我们去探究.有时候我们也会用一些开源的权限验证 ...
- 设计模式(九)装饰者模式(Decorator Pattern)
一.引言 在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类).A ...
- shiro的使用1 简单的认证
最近在重构,有空学了一个简单的安全框架shiro,资料比较少,在百度和google上能搜到的中文我看过了,剩下的时间有空会研究下官网的文章和查看下源码, 简单的分享一些学习过程: 1,简单的一些概念上 ...
- MongoDB进行MapReduce的数据类型
有很长一段时间没更新博客了,因为最近都比较忙,今天算是有点空闲吧.本文主要是介绍MapReduce在MongoDB上的使用,它与sql的分组.聚集类似,也是先map分组,再用reduce统计,最后还可 ...