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 ...
随机推荐
- HTTP Method详细解读(`GET` `HEAD` `POST` `OPTIONS` `PUT` `DELETE` `TRACE` `CONNECT`)
前言 HTTP Method的历史: HTTP 0.9 这个版本只有GET方法 HTTP 1.0 这个版本有GET HEAD POST这三个方法 HTTP 1.1 这个版本是当前版本,包含GET HE ...
- CLR via C# 摘要一:托管程序的执行模型
托管程序的执行模型大致如下: 编译源代码为程序集(dll或exe文件),程序集包括了记录相关信息的元数据和IL代码 执行程序集文件时,启动CLR,JIT负责把IL编译为本地代码并执行 IL是微软推出的 ...
- oracle操作符
Oracle中算术操作符(+)(-)(*)(/) 值得注意的是:/ 在oracle中就相当于显示中的除法 5/2 = 2.5 比较操作符: 其中等号可以换成其他运算符:(后面为该操作符的单条件查询样例 ...
- 前端开发:css技巧,如何设置select、radio 、 checkbox 、file这些不可直接设置的样式 。
前言: 都说程序员有三宝:人傻,钱多,死得早.博主身边的程序“猿”一大半应了这三宝,这从侧面说明了一个问题,只有理性是过不好日子的.朋友们应该把工作与生活分开,让生活变得感性,让工作变得理性,两者相提 ...
- asp.net core 简单部署
目的 练习asp.net core的技术使用.部署等.目前拥有一台阿里云服务器(超级低配版本),安装了centos系统,打算将练习项目发布到该环境中.可能需要做以下准备工作. 以前没接触过linux正 ...
- vs2015 已经支持开发asp .net core 1.0 rc2 程序了
vs2015 已经支持开发asp .net core 1.0 rc2 程序了 http://mp.weixin.qq.com/s?__biz=MzI0MzM1ODczOQ==&mid=2247 ...
- HibernateUtil.java
package com.hkwy.util; import org.hibernate.Session; import org.hibernate.SessionFactory; import org ...
- Node.js写文件的三种方法
Node.js写文件的三种方式: 1.通过管道流写文件 采用管道传输二进制流,可以实现自动管理流,可写流不必当心可读流流的过快而崩溃,适合大小文件传输(推荐) var readStream = fs. ...
- angular的$filter服务
首先,介绍下$filter服务: 1.$filter是用来进行数据格式化的专用服务: 2.AngularJS内置了currency.date.filter.json.limitTo.lowercase ...
- MySQL时间分组查询
表TESTER 字段:id -- INT date -- TIMESTAMP 1.如何按年.月.日分组查询? select DATE_FORMAT(date,'%Y-%m-%d') time, ...