题目链接:ヾ(≧∇≦*)ゝ

大致题意:

给出一个有向图D=(V,E).对于每个点U,定义两种操作a(u),b(u)

操作a(u):删除点U的所有出边,即属于E,操作花费为Ca(u).

操作b(u):删除点U的所有入边,即属于E,操作花费为Cb(u).

求将原图的边集的边全部删除的最小代价,总操作数和具体操作

Solution:

第一问很简单,首先,对于每一个点,把它分成出点和入点。

把每个点的出点与S相连,入点与T相连。边容量分别为删除该点所有入边和出边的花费。

然后对于每条边 a -> b,就把a的出点与b的入点连一条容量为inf的边。

根据最大流=最小割,跑一遍dinic就能得到答案了。

对于第二、三问,我们分别统计a操作和b操作。

我们先对剩余网络进行bfs(),把能够扫到的点都标记为1,不能的标记为0。

对于一个点u,如果要使用a(u),那么显然,需要至少存在一个点v,满足u -> v &&

vis[u]vis[v]0。

而对于点u,如果要使用b(u),只需要满足vis[u]==1就行了。

为了防止重复输出,在定义一个apr数组记录每个数是否加入到答案中就行了。

详见代码

Code:

#include<queue>
#include<ctype.h>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1001
#define M 20001
#define inf 1926081700
using namespace std;
int S,T,head[N];
int n,m,cnt=1;
int ru[N],cu[N];
int ans,vis[N],apr[N];
int t1,t2,fst[N],sec[N];
struct Edge{int nxt,to,val;}edge[M];
void ins(int x,int y,int z){
edge[++cnt].nxt=head[x];
edge[cnt].to=y;edge[cnt].val=z;
head[x]=cnt;
}
namespace Network_Flow{
queue<int> q;
int dep[N];
int bfs(){
memset(dep,0,sizeof(dep));
q.push(S);dep[S]=1;
while(!q.empty()){
int x=q.front();q.pop();
for(int i=head[x];i;i=edge[i].nxt){
int y=edge[i].to,v=edge[i].val;
if(!dep[y]&&v){
q.push(y);
dep[y]=dep[x]+1;
}
}
}
return dep[T];
}
int dfs(int x,int rest){
if(x==T||rest<=0) return rest;
int flow=0;
for(int i=head[x];i;i=edge[i].nxt){
int y=edge[i].to,v=edge[i].val;
if(dep[y]==dep[x]+1&&v){
int now=dfs(y,min(rest,v));
edge[i].val-=now;
edge[i^1].val+=now;
flow+=now;rest-=now;
if(!rest) break;
}
}
return flow;
}
int dinic(){
int maxflow=0;
while(bfs()) maxflow+=dfs(S,inf);
return maxflow;
}
}
void getspj(){
queue<int> s;
s.push(S);vis[S]=1;
while(!s.empty()){
int x=s.front();s.pop();
for(int i=head[x];i;i=edge[i].nxt)
if(!vis[edge[i].to]&&edge[i].val){
s.push(edge[i].to);
vis[edge[i].to]=1;
}
}
apr[S]=apr[T]=1;
}
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int main(){
n=read(),m=read();
S=n*2+1,T=S+1;
for(int i=1;i<=n;i++) ru[i]=read();
for(int i=1;i<=n;i++) cu[i]=read();
for(int i=1;i<=n;i++){
ins(S,i,cu[i]);ins(i,S,0);
ins(i+n,T,ru[i]);ins(T,i+n,0);
}
for(int x,y,i=1;i<=m;i++){
x=read(),y=read();
ins(x,n+y,inf);
ins(n+y,x,0);
}
using namespace Network_Flow;
printf("%d\n",dinic());getspj();
for(int i=1;i<=n;i++)
for(int j=head[i];j;j=edge[j].nxt){
int y=edge[j].to;
if(!vis[i]&&!vis[y]&&!apr[i]){
sec[++t2]=i;
ans++;apr[i]=1;
}
if(!apr[y]&&vis[y]){
fst[++t1]=y%n;
if(!fst[t1]) fst[t1]=n;
ans++;apr[y]=1;
}
}
printf("%d\n",ans);
for(int i=1;i<=t1;i++) printf("%d +\n",fst[i]);
for(int i=1;i<=t2;i++) printf("%d -\n",sec[i]);
return 0;
}

POJ2125 Destroying The Graph的更多相关文章

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

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

  2. POJ2125 Destroying The Graph(二分图最小点权覆盖集)

    最小点权覆盖就是,对于有点权的有向图,选出权值和最少的点的集合覆盖所有的边. 解二分图最小点权覆盖集可以用最小割: vs-X-Y-vt这样连边,vs和X部点的连边容量为X部点的权值,Y部和vt连边容量 ...

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

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

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

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

  5. 【POJ】【2125】Destroying the Graph

    网络流/二分图最小点权覆盖 果然还是应该先看下胡伯涛的论文…… orz proverbs 题意: N个点M条边的有向图,给出如下两种操作.删除点i的所有出边,代价是Ai.删除点j的所有入边,代价是Bj ...

  6. 图论(网络流,二分图最小点权覆盖):POJ 2125 Destroying The Graph

    Destroying The Graph   Description Alice and Bob play the following game. First, Alice draws some di ...

  7. POJ 2125 Destroying The Graph [最小割 打印方案]

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

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

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

  9. AC日记——Destroying The Graph poj 2125

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

随机推荐

  1. 关于Android开发环境的演变

    是不是我天生就不适合安装软件——经过eclipse.jdk.Android Studio的历次安装,我发觉自己似乎永远都装不好.去年eclipse断断续续装了三四天,那时希望能附加C++的软件包,却始 ...

  2. mock使用中出现的错误

    当出现错误Class mocking requires to have objenesis library in the classpath时,缺少了objenesis库文件...下载objenesi ...

  3. C# 文本转语音朗读

    1. 利用DONET框架自带的 SpeechSynthesizer ,缺点是没有感情色彩,抑扬顿挫等. using System; using System.Collections.Generic; ...

  4. 2017-2018 Exp4 恶意代码分析 20155214曾士轩

    目录 Exp4 恶意代码分析 实验内容 使用schtasks指令监控系统运行 主要思路 知识点 启发 Exp4 恶意代码分析 本次实验操使用Windows下的schtasks,sysmon,Proce ...

  5. Caffe上手教程

    Caffe上手教程 入门系列FAQ72 在Unbuntu上安装Caffe828 Windows下安装Caffe1.4K Caffe框架上手教程1.2K Caffe编译运行调试462 Caffe 电脑配 ...

  6. Dynamics 365 支持使用Web Api 通过名称来检索元数据

    关键检索元数据我在之前的一篇博文中稍有提及,当时是为了取实体的picklist字段的属性,但当时的版本只支持通过metadataid检索,而在365中又增加了名称的检索,方便了很多. 本篇依旧用之前博 ...

  7. CF 24 D. Broken robot

    D. Broken robot 链接. 题意: 一个方格,从(x,y)出发,等价的概率向下,向左,向右,不动.如果在左右边缘上,那么等价的概率不动,向右/左,向下.走到最后一行即结束.求期望结束的步数 ...

  8. VS相关

    快速显示函数名称 ctrl+alt+T 显示函数参数说明 ctrl+shift+space,光标放在函数里面 link 1123错误,vs2010的问题. 点击工程-属性-ManifestTool-I ...

  9. [HNOI2018]转盘[结论+线段树]

    题意 题目链接 分析 首先要发现一个结论:最优决策一定存在一种 先在出发点停留之后走一圈 的情况,可以考虑如下证明: 如果要停留的话一定在出发点停留,这样后面的位置更容易取到. 走超过两圈的情况都可以 ...

  10. linux查找进程pid并杀掉

    命令:ps aux | grep `pwd` | grep -v  grep | awk '{print $2}' | xargs kill -9 详细解释[我的有道云笔记,不知道为什么没法直接复制到 ...