【算法#2】与并查集相关的图论问题

最近被和并查集相关的图论问题卡了几次,稍微写一下好了。

分块?咕了,下次再做吧

因为许多例题洛谷里头是没有的,所以把题面讲一下。

一个模板题是UVA1395,非常典型,题面有了就不给了。

为什么会用到并查集呢?判断是否每个点都联通时会用到,那么如何保证联通时差值最小呢?

首先我们把边按边权排序,然后我们枚举较小边的编号,连通左右两点,然后我们从小到大枚举较大边,并且联通这些边的左右块,直到所有点联通,这时的边减去小边即是最小差值。(另外,由于是最大值和最小值的差值,就算两边已经联通也……)不好,其实还是运行最小生成树比较好,因为是否所有点联通无法方便的检测出来。

然后跑一边Kruskal就好了,非常裸的板子题。Record第一次忘记文件输入输出爆零了……

这题是紫书上面有的,后面的两题就没有了。

其中一题是通过并查集去重避免了重复计算优化了暴力算法(根本看不出来是同一个算法啊)并且用到了离线算法。

在遥远的未来,地球被外来文明入侵了,在这危机的关头,人类表现出前所未有的团结,为了让更多的人活下来,联合政府决定联合地球上的所有科学家,共同改造那些被联合政府精心挑选出来的人类,使他们变成拥有超能力的超人,然后派他们去消灭这个地球上的外星生物。这个辉煌而伟大的计划,被命名为,‘’拯救地球‘’计划。

幸运的是你也被选中并且成功被改造成为了超人,每次任务,联合政府都会派你通过传送门去联合政府指定的一个国家,而你的任务就是:你要尽可能多的消灭从这个国家开始往外拓展的外星生物,从而拯救尽可能多的国家。

地球上有n个国家,有m条无向道路,每条道路上只有一个外星生物(地球上的外星生物全部都在道路上,国家里面没有外星生物),每个外星生物都有一个防御值,接着你有q次任务,每次任务联合政府会让你拥有w的攻击力(每次任务的攻击力是一直不变的),然后用传送门将你送去国家x(国家x已经被你拯救),你的任务就是拯救尽可能多的国家。(如果国家a与国家b之间有一条道路,国家a已经被你拯救,并且你的攻击值大于等于这条道路上外星生物的防御值,那么国家b能被你拯救,否则你无法通过这条道路拯救国家b)

对于每次任务,输出你最多能拯救的国家数目,每次任务独立,互不影响

输入描述:

输入第一行三个正整数n,m,q,分别表示地球上的国家数,道路数,以及你的任务数

接下来m行,每行三个整数x,y,w,表示国家x和国家y之间有一条无向道路,并且该道路上只有一个外星怪物,它的防御值为w,保证防御值为正整数

接下来q行,每行两个整数x,w,表示每次任务你会被派到国家x,并且让你拥有w的攻击力,每次任务独立,互不影响

输出描述:

输出共q行,每行一个正整数,表示每次任务你最多能拯救的国家数目

对于20%的数据    n<=(10^{3})    m<=(2 imes10^{3})   q<=(10^{3})$    w<=(10^{9})

对于另外20%的数据    n<=(10^{5})    m<=(2 imes10^{5})   q<=(10^{5})    w<=100

对于再另外20%的数据    n<=(10^{5})    m<=(2 imes10^{5})   q<=(10^{5})    w<=(10^{9})    保证每次任务的输入的x都一样

对于剩余40%的数据    n<=(10^{5})  m<=(2 imes10^{5})   q<=(10^{5})    w<=(10^{9})

每次任务独立,互不影响表示:

每次任务所拯救的国家在其他任务中还是需要重新被拯救的,每次任务所消灭的外星生物在其他任务中还是会重新存在的。

一眼看下来,暴力,直接对于每个给定的点跑一边dfs就完事了。喜提二十分。

然后我们发现对于较小的x能够到达的地方较大的x要是进入其中一个能够到达的地方绝对全部都能达到。

于是我们采用离线算法,维护每一个联通块的大小,把询问按x的大小排序,再把边按边权排序,遍历边,要是左右两边的点不在同一个块里面,合并块并且更新块的大小,如果当前询问的x小于当前边的边权,跳到下一个询问并且将该次询问的答案更新为询问起点所在点所在块的大小。

Code

我们就此开始一起攀登那条漫长的、樱花盛放的坡道。

在一座山上,有n个亭子,连接这这n个亭子的,是m条可以双向行走的步道。每条步道的两旁都栽种着两行樱花树,然而由于光照、土质和打理频率差异,每条步道的美观程度并不一样,第i条步道连接着亭子ai和亭子bi,美观程度为ci。

现在我们想从1号亭子前往n号亭子,并且由于不希望景色出现太大差异,我们希望经过的步道的美观度的最大值和最小值的差尽可能小。请你求出这个最小值。

输入描述:

第一行两个整数n,m,代表亭子和步道的数量。
接下来m行,每行3个整数ai,bi,ci,代表该步道两端的亭子编号和这条步道的美观度。

输出描述:

共一个整数,代表在最优方案中,经过步道的美观度的最大值和最小值的差的最小值。

数据范围:
对于30%的数据,有(nleq10,mleq 20)

对于60%的数据,有(nleq100,mleq200)

对于100%的数据,有(n leq 2000,m leq 4000,1 leq a_i,b_i leq n,1 leq c_i leq 10^5)

保证给定的图是个连通图,但可能有重边或自环。

这个题和第一题大同小异,除了数据范围稍微大了一点,没了(用迪杰斯特拉可以水到80分,我后来写了个DP感觉是对的但是只有70分。)

首先按边权排序

状态((i,j))表示点(i)较大边编号为(j)时的最大较小边。用一个大小为n的数组维护每个点所有可能中最小的差。

状态转移的话,首先找到当前差最小的那个点然后枚举最大边,再遍历连在这个点上的边,更新对方点的……

[dp[dis[id][j].v][max(i,dis[id][j].id)]=max(min(dp[id][i],dis[id][j].id),dp[dis[id][j].v][max(i,dis[id][j].id)]); ]

//dis 指边,包含一个v指向目标点,一个w为边权,一个id为编号,id为当前点的编号,j为当前边的编号。

好像没有问题但是只有70分,难懂也的确,抓虫不好抓。

原文地址:https://www.cnblogs.com/Schwarzkopf-Henkal/p/11830117.html