最小点权覆盖就是,对于有点权的有向图,选出权值和最少的点的集合覆盖所有的边。

解二分图最小点权覆盖集可以用最小割:

  • vs-X-Y-vt这样连边,vs和X部点的连边容量为X部点的权值,Y部和vt连边容量为Y部点的权值,X和Y是原二分图中的边容量为INF。

这一题建二分图是这样的:把原图中的点拆成两个点分别作二分图的X部和Y部,一个入点u+一个出点u-,权值就是题目给的那两个;原图中每条有向弧<u,v>变成二分图的边(u-,v+)。

然后就是建立容量网络,利用最小割求出这个二分图的最小点权覆盖集。

最后,最小割的割边集就对应着一个方案的解。

 #include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define MAXN 222
#define MAXM 222*222*2 struct Edge{
int v,cap,flow,next;
}edge[MAXM];
int vs,vt,NE,NV;
int head[MAXN]; void addEdge(int u,int v,int cap){
edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=;
edge[NE].next=head[u]; head[u]=NE++;
edge[NE].v=u; edge[NE].cap=; edge[NE].flow=;
edge[NE].next=head[v]; head[v]=NE++;
} int level[MAXN];
int gap[MAXN];
void bfs(){
memset(level,-,sizeof(level));
memset(gap,,sizeof(gap));
level[vt]=;
gap[level[vt]]++;
queue<int> que;
que.push(vt);
while(!que.empty()){
int u=que.front(); que.pop();
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(level[v]!=-) continue;
level[v]=level[u]+;
gap[level[v]]++;
que.push(v);
}
}
} int pre[MAXN];
int cur[MAXN];
int ISAP(){
bfs();
memset(pre,-,sizeof(pre));
memcpy(cur,head,sizeof(head));
int u=pre[vs]=vs,flow=,aug=INF;
gap[]=NV;
while(level[vs]<NV){
bool flag=false;
for(int &i=cur[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && level[u]==level[v]+){
flag=true;
pre[v]=u;
u=v;
//aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
aug=min(aug,edge[i].cap-edge[i].flow);
if(v==vt){
flow+=aug;
for(u=pre[v]; v!=vs; v=u,u=pre[u]){
edge[cur[u]].flow+=aug;
edge[cur[u]^].flow-=aug;
}
//aug=-1;
aug=INF;
}
break;
}
}
if(flag) continue;
int minlevel=NV;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
minlevel=level[v];
cur[u]=i;
}
}
if(--gap[level[u]]==) break;
level[u]=minlevel+;
gap[level[u]]++;
u=pre[u];
}
return flow;
} bool S[MAXN];
void dfs(int u){
S[u]=;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && !S[v]) dfs(v);
}
}
int main(){
int n,m,a,b;
while(~scanf("%d%d",&n,&m)){
memset(head,-,sizeof(head));
vs=; vt=n<<|; NV=vt+; NE=;
for(int i=; i<=n; ++i){
scanf("%d",&a);
addEdge(vs,i,a);
}
for(int i=; i<=n; ++i){
scanf("%d",&a);
addEdge(i+n,vt,a);
}
while(m--){
scanf("%d%d",&a,&b);
addEdge(b,a+n,INF);
}
printf("%d\n",ISAP());
memset(S,,sizeof(S));
dfs(vs);
int res[MAXN],resn=;
for(int i=; i<NE; i+=){
if(edge[i].cap==edge[i].flow && S[edge[i^].v] && !S[edge[i].v]){
if(edge[i^].v==vs) res[resn++]=edge[i].v;
else if(edge[i].v==vt) res[resn++]=edge[i^].v;
}
}
printf("%d\n",resn);
for(int i=; i<resn; ++i){
if(res[i]<=n) printf("%d +\n",res[i]);
else printf("%d -\n",res[i]-n);
}
}
return ;
}

POJ2125 Destroying The Graph(二分图最小点权覆盖集)的更多相关文章

  1. POJ 2125 Destroying The Graph (二分图最小点权覆盖集+输出最小割方案)

    题意 有一个图, 两种操作,一种是删除某点的所有出边,一种是删除某点的所有入边,各个点的不同操作分别有一个花费,现在我们想把这个图的边都删除掉,需要的最小花费是多少. 思路 很明显的二分图最小点权覆盖 ...

  2. POJ2125 Destroying The Graph 二分图 + 最小点权覆盖 + 最小割

    思路来源:http://blog.csdn.net/lenleaves/article/details/7873441 求最小点权覆盖,同样求一个最小割,但是要求出割去了那些边, 只要用最终的剩余网络 ...

  3. POJ 2125 Destroying the Graph 二分图最小点权覆盖

    Destroying The Graph Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8198   Accepted: 2 ...

  4. POJ 2125 Destroying The Graph 二分图 最小点权覆盖

    POJ2125 题意简述:给定一个有向图,要通过某些操作删除所有的边,每一次操作可以选择任意一个节点删除由其出发的所有边或者通向它的所有边,两个方向有不同的权值.问最小权值和的解决方案,要输出操作. ...

  5. poj 2125 Destroying The Graph (最小点权覆盖)

    Destroying The Graph http://poj.org/problem?id=2125 Time Limit: 2000MS   Memory Limit: 65536K       ...

  6. 最小点权覆盖集&最大点权独立集

    最小点权覆盖集 二分图最小点权覆盖集解决的是这样一个问题: 在二分图中,对于每条边,两个端点至少选一个,求所选取的点最小权值和. 方法: 1.先对图二分染色,对于每条边两端点的颜色不同 2.然后建立源 ...

  7. POJ2125 Destroying The Graph (最小点权覆盖集)(网络流最小割)

                                                          Destroying The Graph Time Limit: 2000MS   Memo ...

  8. hdu1569 方格取数(2) 最大点权独立集=总权和-最小点权覆盖集 (最小点权覆盖集=最小割=最大流)

    /** 转自:http://blog.csdn.net/u011498819/article/details/20772147 题目:hdu1569 方格取数(2) 链接:https://vjudge ...

  9. POJ 2125 最小点权覆盖集(输出方案)

    题意:给一个图(有自回路,重边),要去掉所有边,规则:对某个点,可以有2种操作:去掉进入该点 的所有边,也可以去掉出该点所有边,(第一种代价为w+,第二种代价为w-).求最小代价去除所有边. 己思:点 ...

随机推荐

  1. 作为一名职高生学习Linux的心酸经历

    当你点进这篇文章的时候,一定会好奇我为什么要用“心酸”这个词,这个词已经太久没被人提起,也许心酸这种感情只能存在于一个人在追中梦想过程中内心角落吧.从小我们总是会被问这样一个问题“你的梦想是什么?”每 ...

  2. Stanford机器学习---第二讲. 多变量线性回归 Linear Regression with multiple variable

    原文:http://blog.csdn.net/abcjennifer/article/details/7700772 本栏目(Machine learning)包括单参数的线性回归.多参数的线性回归 ...

  3. DICOM:DICOM3.0网络通信协议(续)

    转载:http://blog.csdn.net/zssureqh/article/details/44278693 题记: 近一年来一直坚持周末写博客,整理工作和闲暇之余的点点滴滴.对于新知识点.新技 ...

  4. yum 配置

    1.配置yum本地源 # mount /dev/cdrom /mnt/ # vim /etc/yum.repos.d/rhel-source.repo 1 [rhel-source] 2 name=R ...

  5. HM必修1

    高中数学必修一 笔记与拓展 1. 集合与函数概念 集合概念 集合是一个基本的数学概念. 集合是由集合的元素构成的. 当且仅当两个集合中包含着完全相同的元素且都不包含其它元素时两个集合相等. 集合是确定 ...

  6. 【Hadoop】Hive HSQ 使用 && 自定义HQL函数

    4 HQL 4.1 官网 4.1.1 https://cwiki.apache.org/confluence/display/Hive/LanguageManual 4.1.2 性能调优 4.1.2. ...

  7. windows下的unix工具集:UnxUtils

    参考: http://blog.csdn.net/woohello/article/details/8365639 下载: http://sourceforge.net/projects/unxuti ...

  8. iOS UIBezierPath知识介绍

    UIBezierPath是在画图,定制动画轨迹中都有应用. UIBezierPath有许多类方法,能够创建基本的曲线,比如利用一个rect创建一个椭圆path的方法:bezierPathWithOva ...

  9. php配置文件语法

    2013年12月11日 09:21:58 ; The syntax of the file is extremely simple. Whitespace and lines ; beginning ...

  10. codeforces A. Sereja and Bottles 解题报告

    题目链接:http://codeforces.com/problemset/problem/315/A 题目意思:有n个soda bottles,随后给出这n个soda bottles的信息.已知第 ...