首页 > 其他 > 详细

图论之一些好题(8.10)

时间:2019-08-11 09:49:01      阅读:158      评论:0      收藏:0      [点我收藏+]

技术分享图片   技术分享图片

数据范围:O(n3)

弗洛伊德跑出两两之间的最短路

然后加一加判一判

技术分享图片

跑单源最长路

复杂度:O(n2logn)

因为边数是n2

技术分享图片

先跑一遍1为源点的最短路

再建一张把所有有向边都反过来的最短路(1还是源点)来跑

技术分享图片

一:

在跑dij的时候在维护的数里面再塞一个当前的费用,当费用>k的时候就不更新(下一个)

二:

建n*k个点的图

技术分享图片

然后跑个dij

技术分享图片

①:二分答案,把大于等于二分的答案的边加进图中,判是否连通

②:跑dij,更新条件换成if(d[v]>min(d[u],w)) d[v]=min(d[u],w)

③:kruskal找最大生成树,当点1和点n第一次连通的时候,加的那条边就是答案

技术分享图片

技术分享图片

这里酋长的等级不一定是最高的

边权是优惠后的价格

由贵的物品向便宜的物品建边(边权是优惠的价格),从1点开始跑最短路,dis[i]+i的原价是最小价格

考虑等级限制:

枚举等级的区间[l,l+m],其中一定包含酋长的等级

然后枚举的每一个区间跑一次dij

注意人的等级是分散的(类似[1,10]和[2,11]里面包含的人是一样的),所以可以以人的等级为左端点

这样就是n次dij,n<=100

复杂度还是承受的了的

技术分享图片

显然dij被卡爆了

于是我们可以想到一些奇技淫巧

线段树实现dij怎么样?

恐惧.jpg

我们想想怎么优化dij

我们发现priority_queue里面会有很多冗余节点,我们可以合并

但是priority_queue不支持合并

所以我们需要一些奇怪的堆(什么斐波那契堆什么配对堆)

but好像得手写?!!

不会....

平板电视,你值得拥有

 既然不会正解,那我们可以骗分阿

继续用stl的priority_queue

因为输入的边有一部分是随机数据生成器生成的边,所以对最短路的影响似乎不大

而且输入的边似乎只有1e5左右的样子

所以我们就把随机数据生成器生成的边扔掉,说不定就AC了技术分享图片

 诶嘿AC了?技术分享图片

好了这题做完了

插句题外话

priority_que怎么搞合并?

合并两个堆a,b:把点少的那个堆拆掉,把点一个一个放到另一个堆里面,复杂度O(nlog2n)

合并许多堆:二分式拆法

技术分享图片

Prim:

技术分享图片

我们可以把dij搞一搞然后变身prim

证明:

技术分享图片

 

kruskal

 按边权从小到大排序,如果选当前边会成环,则不选,否则就选,直到考虑完所有的边

其实复杂度卡在排序上了(mlogm)

证明需要拟阵的知识

技术分享图片

独立集就是满足遗传性和交换性的集合

| |这个是集合的元素个数

线性相关:

什么是向量:类似一行数组成的东西

技术分享图片

上面就是个向量,格子里面可以填数

如果我们有向量a,b,c

x1*a+x2*b+x3*c=0

则向量a,b,c线性相关

 生成森林:

就是一些不成环的边辣

遗传性证明:如果有一个图没有环,那么去掉任意的边之后都不会形成环,证毕

交换性证明:

我们设A的边数比B的边数少(A,B都是无向生成森林)

既然B不是个环,那么从B里面拆下来一条边安到A上,那么A完全可以安成B原来的样子,所以交换性成立

(xjb玄学证明qwq)

技术分享图片

所以拟阵最优化问题就是kruskal

kruskal的正确性好像就是这样的叭

有什么用呢?如果遇到拟阵贪心题就可以用kruskal就好了

技术分享图片

最小生成树....(撑死就是边多了一点)

技术分享图片

 

 最小生成树+1技术分享图片

 最小生成树+2???

技术分享图片

 

 

先建一个超级水库,连边就是在i建水库的代价

然后最小生成树(保证每个点都能与建出来的超级水库连通)

技术分享图片

这大概是个树

会有一些毒瘤的无法到达的点,我们就把连着这些点的边去掉

然后选出一棵树(不能带环)

然后最小代价就是最小生成树

kruskal怎么排序?

按照边的较低的点从大到小排序,按长度从小到大排序

为什么第一关键字是从大到小排序?

如果是从小到大排序,则只能保证比当前点高度小的点是连通的,但是可能会有毒瘤情况导致求出来的解不够优

emm还是举个例子叭

技术分享图片

另一个神奇的思路:

分层建图,将高度相同的点建在同一层,同一层内是无向边,不同层之间是有向边,同一层内搞最小生成树,然后通过有向边传递到下一层,最后取边权最小值

 

技术分享图片

 

 咕咕咕~?

晚上网络流time走起

技术分享图片

技术分享图片

 

 技术分享图片

技术分享图片

技术分享图片

k进行二进制拆分

技术分享图片

 

 技术分享图片

还有tarjan+并查集(离线,O(n))

dfs序+RMQ搞lca:

我们先进行dfs,每到达一个点,就把一个点放进一个序列里面(如果回溯时到达序列中有的点,则再放一遍)

如果要算a,b的lca,就找到最后出现的a和第一次出现的b,它们中间一定会有它们的lca

这样它们中间的那个深度最浅的点就是lca了(用RMQ维护深度最浅的点)

技术分享图片

技术分享图片

树链剖分

技术分享图片

一种叫重量剖分,另一种叫常量剖分

默认重量剖分

技术分享图片

 

 注意重链的出发点不一定是根,可以是任意的节点

每一个点必定属于一个重链

如果从任意一点网上走,则经过的重链的条数和轻边的边数是等级别的(都是logn级别的)

why?

轻边和重链是交替走的,因为如果走完一条重链,再走一条重链,那它们就是一条重链了(即不存在两条连续的重链)

所以重链的条数≤轻边数量+1

如果我当前走过了一条轻边,则说明我走过的那个点的父亲的子树至少是那个点的子树的两倍。所以如果我一直走轻边,只需要最多logn次就能走完这棵树。

dfs:

技术分享图片

树链剖分求lca
技术分享图片

技术分享图片

先判ta是否==tb

如果a,b有祖宗关系:看谁的深度浅,谁就是lca

深度较深的:到a-->topa,topa-->轻边,然后递归求解

复杂度:o(logn)

技术分享图片

树链剖分的特点:重链在树上是连续一段

求a到b路径上的信息:先找到lca,然后就是一段重链,一个轻边blabla

把树摊成个区间,这样就可以求一段区间的最值

求最值:线段树来维护(只维护重链,轻边暴力解决)

技术分享图片

就是要求两个操作:

1.把某个边权的值改为t

2.求a到b路径上的最小值

先把边权摊到儿子上

改边权:找到儿子u,再找到dfn[u],在线段树里单点修改

求最小值:找到lca的那两条链,把链上的重链所在序列的区间在线段树里找到最大值

bzoj 1036

技术分享图片

...和上题差不多

操作3:把求最大值换成求和

技术分享图片

线线线线线段树

 

技术分享图片

这个线段树有点难qwq

看左儿子和右儿子中间那个相不相同

染色的tag

技术分享图片

先求个最小生成树,不在的边就不管

如果在呢?

树会被分成两块,只需要在非树边里面找一条权值最小的连接这两个块的边就可以了

一个非树边能够缝合一个数:当去掉它包含的一段链里的边

所以可以在树上每个边搞一个权值(初始为inf),然后与覆盖它的非树边的权值取min,即可快速查询可以缝合树的最小边权

技术分享图片

技术分享图片

技术分享图片

qwq

证明:没有

技术分享图片

缩点+拓扑排序

如果不考虑n的大小:弗洛伊德传递闭包

更好一点:传递闭包

大小为k的强连通分量贡献:k2

然后求一个scc可以到达的scc: bitset压位

然后再考虑每个scc的大小(原数*k2

bitset:

bitset<1000000>a

a就是一个长度为1000000的二进制数

a[i]访问a的第i为

下标从0开始

技术分享图片

缩点,统计出度为0的点

1个点:出度为0的点的那一坨牛

>1:没有牛

技术分享图片 

 缩点

T1:统计入度为0的点的数量
T2:max(入度为0的点的数量,出度为0的点的数量)

T3:给出连边方案(雾)

总之要把入度为0的点和出度为0的点弄没

找一个出度为0的点,让它连向一个无法到达的入度为0的点,重复这个操作

 

图论之一些好题(8.10)

原文:https://www.cnblogs.com/lcez56jsy/p/11331178.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!