[洛谷]P3729 曼哈顿计划EX(最小割树/等价流树)
题目大意:给出一张n个点m条边的无向图,每个点有点权,q次询问,每次给出k,要求选出若干个点点权之和不小于k,求一个最大的值x,使得选出的点中任意两点之间至少有x条互不相交的链。(n<=550,m<=3000,q<=2017)
当时看到这题一看就不可做 看了题解说什么等价流树也看不懂 后来FallDream大佬做了一题最小割树 看了看网上大神极短的说明加上自己大量的脑补终于搞懂了这玩意儿 另外貌似等价流树就是最小割树
最小割树的思路大概是先任意求出两点之间的最小割,并把整张图按最小割分成两个部分,并用这个最小割更新所有被分到不同部分的点对之间的最小割,然后对分出的两个部分分治,值得注意的是即使点集被分治分小了,每次我们更新答案仍然要更新整张图。
通过这个分治过程,我们会得到n-1个最小割,并能组成一个树形结构,每次求两点之间最小割时,两点之间连边,边权为最小割,图上任意两点之间的最小割就是树上路径的最小值,这样我们只要做O(n)次网络流就能求出O(n^2)个点对之间的最小割。
下面考虑这题,两点之间至少有x条不相交的链就是说最大流/最小割大等x,假设我们选出了若干个点,那么这些点两两之间最小割的最小值,就是在等价流树上要让这些点连通所必要的边的最小值,我们把等价流树上的边从大到小加进带权并查集,维护各个连通块的权值和,问题即可解决。
自己乱写了一个比较舒服的模板。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
inline int read()
{
int x;char c;
while((c=getchar())<''||c>'');
for(x=c-'';(c=getchar())>=''&&c<='';)x=x*+c-'';
return x;
}
#define MN 550
#define MM 3000
#define INF 0x7FFFFFFF
struct edge{int nx,t,w;}e[MM*+];
int m,S,T,h[MN+],en,d[MN+],q[MN+],qn,c[MN+];
int w[MN+],uu[MM+],vv[MM+],cnt,f[MN+],ans[MM+];
vector<int> v[MN+];
struct tredge{int u,v,w;}t[MN+];
bool cmp(tredge a,tredge b){return a.w>b.w;}
struct query{int k,id;}r[MM+];
bool cmpk(query a,query b){return a.k<b.k;}
int gf(int k){return f[k]?f[k]=gf(f[k]):k;}
inline void ins(int x,int y)
{
e[++en]=(edge){h[x],y,};h[x]=en;
e[++en]=(edge){h[y],x,};h[y]=en;
}
bool bfs()
{
int i,j;
memset(d,,sizeof(d));
for(d[q[i=qn=]=S]=;i<=qn;++i)for(j=c[q[i]]=h[q[i]];j;j=e[j].nx)
if(e[j].w&&!d[e[j].t])d[q[++qn]=e[j].t]=d[q[i]]+;
return d[T];
}
int dfs(int x,int r)
{
if(x==T)return r;
int k,u=;
for(int&i=c[x];i;i=e[i].nx)if(e[i].w&&d[x]+==d[e[i].t])
{
k=dfs(e[i].t,min(r-u,e[i].w));
u+=k;e[i].w-=k;e[i^].w+=k;
if(u==r)return u;
}
return d[x]=,u;
}
void color(int x)
{
c[x]=;
for(int i=h[x];i;i=e[i].nx)
if(e[i].w&&!c[e[i].t])color(e[i].t);
}
void build(int x)
{
if(v[x].size()<)return;
t[++cnt].u=S=x;t[cnt].v=T=v[x][v[x][]==x];
memset(h,,sizeof(h));en=;
for(int i=;i<=m;++i)ins(uu[i],vv[i]);
while(bfs())t[cnt].w+=dfs(S,INF);
memset(c,,sizeof(c));
color(x);
for(int i=;i<v[x].size();++i)while(i<v[x].size()&&!c[v[x][i]])
v[T].push_back(v[x][i]),v[x].erase(v[x].begin()+i);
build(T);build(x);
}
int main()
{
int n,q,i,j,k=;
n=read();m=read();q=read();
for(i=;i<=n;++i)k=max(k,w[i]=read()),v[].push_back(i);
for(i=;i<=m;++i)uu[i]=read(),vv[i]=read();
for(i=;i<=q;++i)r[i]=(query){read(),i};
build();
sort(r+,r+q+,cmpk);
sort(t+,t+n,cmp);
for(j=;j<=q&&r[j].k<=k;++j)ans[r[j].id]=INF;
for(i=;i<n;++i)
{
k=max(k,w[gf(t[i].u)]+=w[gf(t[i].v)]);
f[gf(t[i].v)]=gf(t[i].u);
for(;j<=q&&r[j].k<=k;++j)ans[r[j].id]=t[i].w;
}
for(i=;i<=q;++i)
if(ans[i]==INF)puts("nan");
else if(ans[i])printf("%d\n",ans[i]);
else puts("Nuclear launch detected");
}
[洛谷]P3729 曼哈顿计划EX(最小割树/等价流树)的更多相关文章
- 【洛谷P3329】 [ZJOI2011]最小割(最小割树)
洛谷 题意: 给出一个无向图,之后有\(q,q\leq 30\)组询问,每组询问有一个\(x\),回答有多少点对\((a,b)\)其\(a-b\)最小割不超过\(x\). 思路: 这个题做法要最小割树 ...
- 洛谷P4014 分配问题【最小/大费用流】题解+AC代码
洛谷P4014 分配问题[最小/大费用流]题解+AC代码 题目描述 有 n 件工作要分配给 n 个人做.第 i 个人做第 j 件工作产生的效益为c ij. 试设计一个将 n 件工作分配给 n 个人做的 ...
- ACM/ICPC 之 伞兵-最小割转最大流(POJ3308)
//以行列建点,伞兵位置为单向边-利用对数将乘积转加法 //最小割转最大流 //Time:63Ms Memory:792K #include<iostream> #include<c ...
- 【Luogu】P2057善意的投票(最小割转最大流)
题目链接 也算水题一道吧,不过Round1感性理解一下就xjb建了个图,40 Round2仔细分析了一会,理性建了个图,90 然后分析了半天……改大数组就A了…… 从S到所有值为1的点连一条inf的边 ...
- 洛谷P4299 首都(BZOJ3510)(LCT,树的重心,二分查找)
Update:原来的洛谷U21715已成坑qwq 已经被某位管理员巨佬放进公共题库啦!又可以多一个AC记录啦! 洛谷题目传送门 其实也可以到这里交啦 思路分析 动态维护树的重心 题目中说到国家的首都会 ...
- [NOI导刊2010提高&洛谷P1774]最接近神的人 题解(树状数组求逆序对)
[NOI导刊2010提高&洛谷P1774]最接近神的人 Description 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某 ...
- 洛谷P3380 【模板】二逼平衡树(树套树)(线段树+树状数组)
P3380 [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数 ...
- 【BZOJ2595_洛谷4294】[WC2008]游览计划(斯坦纳树_状压DP)
上个月写的题qwq--突然想写篇博客 题目: 洛谷4294 分析: 斯坦纳树模板题. 简单来说,斯坦纳树问题就是给定一张有边权(或点权)的无向图,要求选若干条边使图中一些选定的点连通(可以经过其他点) ...
- 洛谷 P3380 【模板】二逼平衡树(树套树)-线段树套splay
P3380 [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数 ...
随机推荐
- WORK
团队展示 队伍信息 队名:小狗队 队长:刘映华(201421122021) 队员:兰运良(201421122030).郭和水(201421122017) 团队项目描述 团队项目描述是基于之前的四则运算 ...
- defaultdict使用及__missing__理解
import collections import re WORD_RE = re.compile(r'\w+') index = collections.defaultdict(list) #用li ...
- 团队作业4——第一次项目冲刺(Alpha版本)11.14
a. 提供当天站立式会议照片一张 举行站立式会议,讨论项目安排: PM对整个项目的需求进行讲解: 全队对整个项目的细节进行沟通: 对整个项目的开发计划进行分析,分配每天的任务: 统一确定项目的开发环境 ...
- 从一次输入框无法输入的bug,谈如何限制输入框输入类型
bug的产生和修改 上周临近周末休息的时候,一个同事跑过来了,对我说:"阿伦啊,有一个页面出问题了,火狐浏览器所有的input都没法输入了."我一听,是不是你给加了什么属性,让in ...
- windows 7 netsh wlan命令连接wifi
显示本机保存的profiles,配置文件是以wifi的ssid命名的. netsh wlan show profiles 用netsh wlan connect name=00_1111 连接其中一个 ...
- linux的脚本应用for循环答应变量
#!/bin/bash for var in A B C ; do echo "var is $var" done
- C# 启动 SQL Server 服务
//首先要添加 System.ServiceProcess.dll 引用 ServiceController sc = new ServiceController("MSSQLSERVER& ...
- redis命令详解
redis中添加key value元素:set key value; 获取元素:get key ; redis中添加集合:lpush key value1 value2 value ...
- Let's Encrypt,免费好用的 HTTPS 证书
很早之前我就在关注 Let's Encrypt 这个免费.自动化.开放的证书签发服务.它由 ISRG(Internet Security Research Group,互联网安全研究小组)提供服务,而 ...
- ssh_maven之controller层开发
我们已经完成了前两层的开发,现在 只剩下我们的controller层了,对于这一层,我们需要创建一个动作类CustomerAction,另外就是我们的strutss.xml以及我们的applicati ...