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 ...
随机推荐
- node实现watcher的困境
@(node,watcher) watcher,在如今的前端领域已经数见不鲜了.目前流行的gulp流程工具提供了watcher的选项,是我们在开发过程中不需要手动进行触发构建流程,转而根据文件(目录) ...
- Oracle数据库文件路径变更
环境:RHEL 6.4 + Oracle 11.2.0.3 情景一:只是部分普通数据文件迁移,可以在线操作. 1.将对应表空间offline,移动数据文件到新路径 2.数据文件alter databa ...
- 网页或微信小程序中使元素占满整个屏幕高度
在项目中经常要用到一个容器元素占满屏幕高度和宽度,然后再在这个容器元素里放置其他元素. 宽度很简单就是width:100% 但是高度呢,我们知道的是height:100%必须是在父元素的高度给定了的情 ...
- 浅玩JavaScript的数据类型判断
前言 平常在需要进行类型判断时,随手拿起typeof就像手枪一样只管突突突...也没有仔细的去了解它的具体特性. 所以这里就利用空闲时间,来做一个较为详细的了解. 首先我们来全面看一遍typeof类型 ...
- JavaScript RegExp 基础详谈
前言: 正则对于一个码农来说是最基础的了,而且在博客园中,发表关于讲解正则表达式的技术文章,更是数不胜数,各有各的优点,但是就是这种很基础的东西,如果我们不去真正仔细研究.学习.掌握,而是抱着需要的时 ...
- java web学习总结(三十一) -------------------EL表达式
一.EL表达式简介 EL 全名为Expression Language.EL主要作用: 1.获取数据 EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的web域 中检索java对象.获取数 ...
- JS+CSS3人物奔跑动画
查看效果:http://hovertree.com/texiao/jquery/58/ 效果图: 代码: <!DOCTYPE html> <html> <head> ...
- jQuery选择器笔记
1.$(this).hide() - 隐藏当前元素 $("p").hide() - 隐藏所有段落 $(".test").hide() - 隐藏所有 class= ...
- 用Kotlin语言重新编写Plaid APP:经验教训(II)
原文标题:Converting Plaid to Kotlin: Lessons learned (Part 2) 原文链接:http://antonioleiva.com/plaid-kotlin- ...
- 最快让你上手ReactiveCocoa之基础篇
前言 很多blog都说ReactiveCocoa好用,然后各种秀自己如何灵活运用ReactiveCocoa,但是感觉真正缺少的是一篇如何学习ReactiveCocoa的文章,这里介绍一下. 1.Rea ...