https://www.luogu.org/problemnew/show/P4174

最大权闭合子图的模板

每个通讯站建一个点,点权为-Pi;每个用户建一个点,点权为Ci,分别向Ai和Bi对应的点连边;然后就可以跑了

方法是:

建新源S和新汇T,从S向所有正权点连边,容量为点权值;从所有负权点向T连边,容量为点权值的相反数;原图中所有边容量设为无穷大

跑S到T最大流

原因:(网上都有,自己研究的也不知道有没有偏差)

找出图的任意一个割,其中:

显然不可能割掉容量为无穷大的边;

割掉一条S到u的边,表示不取点u,同时舍弃u点的价值;

割掉一条v到T的边,表示取点v,同时加上v点的代价;

能保证割完这个割中的边后,S到T不连通,即保证不存在任意路径,从S到u经过一些点到v再到T,即保证不存在一个u点需要被取,但是它能到达的一个节点v没有被取。

因此,一个割对应一种闭合子图方案

同样的,可以证明一种闭合子图方案一定对应这样的一个割。

那么,求出最小割,就求出了最小的"舍弃的价值和"+"加上的代价和",设其为x,则最大权闭合子图的点权和等于所有正点权和-x,而最小割等于最大流

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
namespace F
{ struct E
{
int to,nxt,from,cap,flow;
}e[];
int f1[],ne=;
int S,T,n;
int d[];
bool bfs()
{
int k,u;
memset(d,,sizeof(int)*(n+));
queue<int> q;
q.push(S);d[S]=;
while(!q.empty())
{
u=q.front();q.pop();
for(k=f1[u];k;k=e[k].nxt)
if(!d[e[k].to]&&e[k].cap>e[k].flow)
{
d[e[k].to]=d[u]+;
//if(e[k].to==T) return 1;
q.push(e[k].to);
}
}
//return 0;
return d[T];
}
int cur[];
int dfs(int u,int x)
{
if(u==T||x==) return x;
int flow=,f;
for(int &k=cur[u];k;k=e[k].nxt)
if(e[k].cap>e[k].flow&&d[e[k].to]==d[u]+)
{
f=dfs(e[k].to,min(x-flow,e[k].cap-e[k].flow));
e[k].flow+=f;e[k^].flow-=f;flow+=f;
if(flow==x) return flow;
}
return flow;
}
int solve()
{
int flow=;
while(bfs())
{
memcpy(cur,f1,sizeof(int)*(n+));
flow+=dfs(S,0x3f3f3f3f);
}
return flow;
}
void me(int a,int b,int c)
{
e[++ne].to=b;e[ne].nxt=f1[a];f1[a]=ne;
e[ne].from=a;e[ne].cap=c;
e[++ne].to=a;e[ne].nxt=f1[b];f1[b]=ne;
e[ne].from=b;e[ne].cap=;
} }
int n,m;
int main()
{
int i,a,b,c,ss=,t;
scanf("%d%d",&n,&m);F::n=n+m+;F::S=n+m+;F::T=n+m+;
for(i=;i<=n;i++)
{
scanf("%d",&t);
F::me(i,F::T,t);
//ss-=t;
}
for(i=;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
F::me(F::S,i+n,c);
F::me(i+n,a,0x3f3f3f3f);
F::me(i+n,b,0x3f3f3f3f);
ss+=c;
}
printf("%d",ss-F::solve());
return ;
}

upd20190307:

貌似cf出了重题,但是要改longlonghttps://codeforces.com/problemset/problem/1082/G


https://www.luogu.org/problemnew/show/P2762

这题也是一样,但是要输出方案

按照上面的方法,只要找出任意一组最小割就容易找到输出方法了

怎么找最小割?只要找出跑出最大流以后,找出残量网络中源点S能到达的点集s1,取t1=所有点的集合-s1,那么割掉原图中所有s1,t1间的边即可

这里面有一个看起来比较靠谱的证明:https://hihocoder.com/problemset/problem/1378

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
namespace F
{ struct E
{
int to,nxt,from,cap,flow;
}e[];
int f1[],ne=;
int S,T,n;
int d[];
bool bfs()
{
int k,u;
memset(d,,sizeof(int)*(n+));
queue<int> q;
q.push(S);d[S]=;
while(!q.empty())
{
u=q.front();q.pop();
for(k=f1[u];k;k=e[k].nxt)
if(!d[e[k].to]&&e[k].cap>e[k].flow)
{
d[e[k].to]=d[u]+;
//if(e[k].to==T) return 1;
q.push(e[k].to);
}
}
//return 0;
return d[T];
}
int cur[];
int dfs(int u,int x)
{
if(u==T||x==) return x;
int flow=,f;
for(int &k=cur[u];k;k=e[k].nxt)
if(e[k].cap>e[k].flow&&d[e[k].to]==d[u]+)
{
f=dfs(e[k].to,min(x-flow,e[k].cap-e[k].flow));
e[k].flow+=f;e[k^].flow-=f;flow+=f;
if(flow==x) return flow;
}
return flow;
}
int solve()
{
int flow=;
while(bfs())
{
memcpy(cur,f1,sizeof(int)*(n+));
flow+=dfs(S,0x3f3f3f3f);
}
return flow;
}
void me(int a,int b,int c)
{
e[++ne].to=b;e[ne].nxt=f1[a];f1[a]=ne;
e[ne].from=a;e[ne].cap=c;
e[++ne].to=a;e[ne].nxt=f1[b];f1[b]=ne;
e[ne].from=b;e[ne].cap=;
} } int n,m;
char tools[];
bool ok[];
int tt[];
void work()
{
int k,u;
memset(ok,,sizeof(bool)*(n+));
queue<int> q;
q.push(F::S);ok[F::S]=;
using F::f1;using F::e;
while(!q.empty())
{
u=q.front();q.pop();
for(k=f1[u];k;k=e[k].nxt)
if(!ok[e[k].to]&&e[k].cap>e[k].flow)
{
q.push(e[k].to);
ok[e[k].to]=;
}
}
for(int i=;i<=F::n;i++)
if(ok[i])
{
for(k=f1[i];k;k=e[k].nxt)
if(k%==&&!ok[e[k].to])
tt[++tt[]]=k;
}
}
bool nok[];
int main()
{
int i,a,b,c,ss=,t;
scanf("%d%d",&m,&n);F::n=n+m+;F::S=n+m+;F::T=n+m+;
for(i=;i<=m;i++)
{
scanf("%d",&t);
F::me(F::S,i,t);
ss+=t;
cin.getline(tools,);
int ulen=,tool;
while(sscanf(tools+ulen,"%d",&tool)==)
{
F::me(i,tool+m,0x3f3f3f3f);
if(tool==)
ulen++;
else
{
while(tool)
{
tool/=;
ulen++;
}
}
ulen++;
}
}
for(i=;i<=n;i++)
{
scanf("%d",&t);
F::me(i+m,F::T,t);
}
int an=ss-F::solve();
work();
for(i=;i<=tt[];i++)
{
using F::e;
if(e[tt[i]].from==F::S)
{
nok[e[tt[i]].to]=;
}
}
for(i=;i<=m;i++)
if(!nok[i])
printf("%d ",i);
puts("");
for(i=;i<=tt[];i++)
{
using F::e;
if(e[tt[i]].to==F::T)
{
printf("%d ",e[tt[i]].from-m);
}
}
puts("");
printf("%d",an);
return ;
}

洛谷 P4174 [NOI2006]最大获利 && 洛谷 P2762 太空飞行计划问题 (最大权闭合子图 && 最小割输出任意一组方案)的更多相关文章

  1. 洛谷P2762 太空飞行计划问题(最大权闭合图)

    题意 有$m$个实验,$n$中器材,每个实验需要使用一些器材 每个实验有收入,每个器材有花费 最大化收入 - 花费 Sol 最大权闭合图的经典应用 从$S$向每个实验连流量为该实验收入的边 从每个器材 ...

  2. 【最大权闭合子图 最小割】bzoj1497: [NOI2006]最大获利

    最大权闭合子图的模型:今天才发现dinic板子是一直挂的…… Description 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU集团旗下的CS&T通讯公司在 ...

  3. 洛谷 P2762 太空飞行计划问题 【最大权闭合子图+最小割】

    --一道难在读入的题. 最后解决方案直接getline一行然后是把读优拆掉放进函数,虽然很丑但是过了. 然后就是裸的最大权闭合子图了,把仪器当成负权点向t连流量为其价格的边,s向实验连流量为实验报酬的 ...

  4. bzoj 1497 [NOI2006]最大获利【最大权闭合子图+最小割】

    不要被5s时限和50000点数吓倒!大胆网络流!我一个5w级别的dinic只跑了1s+! 看起来没有最大权闭合子图的特征--限制,实际上还是有的. 我们需要把中转站看成负权点,把p看成点权,把客户看成 ...

  5. 洛谷 P2762 太空飞行计划问题 P3410 拍照【最大权闭合子图】题解+代码

    洛谷 P2762 太空飞行计划问题 P3410 拍照[最大权闭合子图]题解+代码 最大权闭合子图 定义: 如果对于一个点集合,其中任何一个点都不能到达此集合以外的点,这就叫做闭合子图.每个点都有一个权 ...

  6. 洛谷 P4174 [NOI2006]最大获利 解题报告

    P4174 [NOI2006]最大获利 题目描述 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU 集团旗下的 CS&T 通讯公司在新一代通讯技术血战的前夜,需要 ...

  7. 洛谷P4174 [NOI2006]最大获利(最大流)

    题目描述 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU 集团旗下的 CS&T 通讯公司在新一代通讯技术血战的前夜,需要做太多的准备工作,仅就站址选择一项,就需 ...

  8. [洛谷P4174][NOI2006]最大获利

    题目大意:同Petya and Graph,数据范围改成$n\leqslant5\times10^3,m\leqslant5\times10^4$ 题解:同上 卡点:无 C++ Code: #incl ...

  9. 洛谷 [P2762] 太空飞行计划问题

    最大权闭合子图 胡伯涛论文真是个好东西.jpg 求一个有向图的最大权闭合子图,常应用于有先决条件的最优化问题中 将所有正权点与源点相连,容量为点权; 将所有负权点与汇点相连,容量为点权的相反数; 将原 ...

随机推荐

  1. margin在块元素、内联元素中的区别 padding

    (1)margin在块元素.内联元素中的区别 HTML(这里说的是html标准,而不是xhtml)里分两种基本元素,即block和inline.顾名思义,block元素就是以”块”表现的元素(bloc ...

  2. SDUT OJ 之 1571 《人品,有没有?》 字符串的处理问题

    人品,有木有? Time Limit: 1000ms   Memory limit: 32768K  有疑问?点这里^_^ 题目描述 新一届的山东理工大学ACM网络擂台赛就要开始啦!听说晋级的选手有机 ...

  3. Java锁机制-重入锁

    锁的种类: 读写锁   悲观锁  乐观锁 CSA无锁  自旋锁  AQS 非公平锁 公平锁 互斥锁 排它锁  分布式锁(redis实现 和 zk实现) 轻量级锁(lock),重量级锁(synchron ...

  4. MYSQL进阶学习笔记十四:MySQL 应用程序优化!(视频序号:进阶_32)

    知识点十五:MySQL 的应用程序优化(32) 一.访问数据库采用连接池 把连接当做对象或设备,统一放在‘连接池’里.凡是需要访问数据库的地方都从连接池里取连接 二.采用缓存减少对于MySQL的访问: ...

  5. ubuntu nginx 安装 certbot(letsencrypt)

    https://certbot.eff.org 到上面网站按照步骤安装certbot, 安装完成后,certbot 生成证书有两种方式 第一种:standalone模式,certbot 会启动自带的n ...

  6. Vijos P1794 文化之旅

    标签:                                         搜索图结构 最短路                                    NOIP普及组2012 ...

  7. codeforces 702C C. Cellular Network(水题)

    题目链接: C. Cellular Network time limit per test 3 seconds memory limit per test 256 megabytes input st ...

  8. (QACNN)自然语言处理:智能问答 IBM 保险QA QACNN 实现笔记

    follow: https://github.com/white127/insuranceQA-cnn-lstm http://www.52nlp.cn/qa%E9%97%AE%E7%AD%94%E7 ...

  9. 微信小程序自定义下导航页面切换效果的合理写法

    上图::: 导航模板内容页面的定义: <template name="naviBot">   <view class='navwrap t_cen font_26 ...

  10. 「UOJ#117」 欧拉回路

    欧拉回路 - 题目 - Universal Online Judge 题意: 给定有向图或无向图,求一条欧拉回路. 题解 心路历程:woc什么傻哔东西->哇真香我的吗!(逃 首先我知道很多人把欧 ...