[洛谷]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的值 修改某一位值上的数 ...
随机推荐
- 学号:201621123032 《Java程序设计》第10周学习总结
1:本周学习总结 1.1.:以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2:书面作业 2.1.:常用异常--结合题集题目7-1回答 2.1.1:自己以前编写的代码中经常出现什么异常.需要捕 ...
- java第5章学习总结
学号20145336 <Java程序设计>第5周学习总结 教材学习内容总结 try catch JVM会先尝试执行try区块中的内容,若发生错误且与catch后面的类型相符,则执行catc ...
- 22.C++- 继承与组合,protected访问级别
在C++里,通过继承和组合实现了代码复用,使得开发效率提高,并且能够通过代码看到事物的关系 组合比继承简单,所以在写代码时先考虑能否组合,再来考虑继承. 组合的特点 将其它类的对象作为当前类的成员使用 ...
- 为微软samples-for-ai贡献代码是种怎么样的体验?
推送原文链接:传送门 关注SomedayWill,了解为微软项目贡献代码的始终. 还记得微软神器samples-for-ai吗?它可不仅仅可以用来安装框架,它其实是个开源的AI样例库,以Visual ...
- 《javascript设计模式与开发实践》阅读笔记(16)—— 状态模式
状态模式 会区分事物内部的状态,事物内部状态的改变往往会带来事物的行为改变.比如电灯的开关是开还是关,在外界的表现就完全不同. 电灯例子 按照常规思路,实现一个电灯就是构造一个电灯类,然后指定一下它的 ...
- 10-TypeScript中的接口
接口是一种规约的约定,从接口继承的类必须实现接口的约定.在高级开发中,通常接口是用于实现各种设计模式的基础,没有接口,设计模式无从谈起. 定义接口: interface ILog{ recordlog ...
- 常用Mysql数据库操作语句
用户管理: 1.新建用户: 语法msyql>CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 说明: username - 你将创建 ...
- Sudoku 第一步
看到这个问题的思路是先解决生成数独生成器的编写,然后再解决数独求解的问题.最开始第一想法就是暴力求解,仔细算一下复杂度,发现这肯定耗时很久,于是看了很多博客(见转载).我们用回溯搜出来正解.
- vscode使用shell
https://stackoverflow.com/questions/42606837/how-to-use-bash-on-windows-from-visual-studio-code-inte ...
- GIT入门笔记(7)- 修改文件并向版本库提交
1.修改文件vi readme.txt git status 发现被修改的文件列表git diff readme.txt 2.git add readme.txt git status --注意gi ...