首页 > 其他分享 >好题——图论

好题——图论

时间:2024-05-01 09:45:27浏览次数:23  
标签:图论 23 int 短路 路径 好题 此题 式子

前言

本文章将会持续更新,主要是一些个人觉得比较妙的题,主观性比较强(给自己记录用的),有讲错请补充。

带 !号的题是基础例题,带 * 号的是推荐首先完成的题(有一定启发性的)。

图论

最短路

P1119 灾后重建

此题看到以后以为是很简单的最短路问题(实际也不难),就写了 dijkstra ,然后光荣的 tie 了。

看数据:N 才 \(200\),想到 Floyd 算法,此题很好的利用了 Floyd 的本质,个我这种只记得模板的当头一棒。

通过其他的点进行中转来求的两点之间的最短路。我们知道,两点之间有多条路,如果换一条路可以缩短距离的话,就更新最短距离。而它最本质的思想,就是用其他的点进行中转,从而达到求出最短路的目的。
那么,如何进行中转呢?两点之间可以由一个点作为中转点更新最短路径,也可以通过多个点更新最短路径。

化解到此题:

按照时间顺序更新每一个可用的点(即修建好村庄),对于每个时间点进行两点之间询问,求对于目前建设的所有村庄来说任意两点之间的最短路

上文引用第一篇题解

void floyd(int k)
{
	for(int i=0;i<n;i++)
	for(int j=0;j<n;j++)
	if(f[i][j]>f[i][k]+f[k][j])	f[i][j]=f[i][k]+f[k][j];
}

此题又友好的帮你把村庄的修建时间,询问的时间排好序了,用指针扫一遍就可以了,不需要每次询问都从头算一遍。

code
#include<bits/stdc++.h>
using namespace std;
const int N=200+10;
int f[N][N],a[N][N];
int ti[N],n,m,Q;
void fl(int k)
{
	for(int i=0;i<n;i++)
	for(int j=0;j<n;j++)
	if(f[i][j]>f[i][k]+f[k][j])	f[i][j]=f[i][k]+f[k][j];
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++)	scanf("%d",&ti[i]);
	for(int i=0;i<n;i++)
	for(int j=0;j<n;j++)
	f[i][j]=1e9+10;
	for(int i=1;i<=n;i++)
	f[i][i]=0; 
	for(int i=1;i<=m;i++)
	{
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		f[u][v]=f[v][u]=w;
	}	
	
	scanf("%d",&Q);
	int now=0;
	while(Q--)
	{
		int u,v,t;
		scanf("%d%d%d",&u,&v,&t);
		while(now<n&&ti[now]<=t)	floyd(now),now++;
		if(ti[u]>t||ti[v]>t||f[u][v]==1e9+10)	puts("-1");
		else printf("%d\n",f[u][v]);
	}
	return 0;
}

! P6175 无向图的最小环问题

上题写到 floyd 的本质是:通过其他的点进行中转来求的两点之间的最短路。

而每一个点也可以成为一个环的中转点。

在代码上就是:

for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{

	if(i!=j&&a[i][k]&&a[k][j])
	ans=min(ans,f[i][j]+a[i][k]+a[k][j]);
	f[i][j]=min(f[i][j],f[i][k]+f[k][j]); 
}

又是 floyd 的一个好应用。

! P2149 [SDOI2009] Elaxia的路线

简单来说就是:无向图中,两对点间最短路的最长公共路径。

这里首先要把最短路的路径找出来,当然这个路径不止一条,然后找重叠的部分,按拓扑序求一次 dp 找最大值。

先用 dijkstra 分别从起点、终点开始跑一次单元最短路,然后一条边一条边的比对,看是否从起点到这条边加上从终点到这条边在加上这条边的边权,是否是从起点到终点的最短路(次短路也要这么写只不过是替换罢了)。

这道题是求两点对最短路的公共边,所以要跑四次单源最短路,因为路径重叠可以通向重叠也可以反向重叠,所以要跑两次 dp。

此题重在学习找最短路径是的替换思想,这在求次短路也体现了。

P5304 [GXOI/GZOI2019] 旅行者

此题标答是二进制拆分,把 \(k\) 个数按位数二进制拆分,枚举位数,这一位是 \(1\) 的放在一个集合,为 \(0\) 的放在一个集合,用一个超级源点链接第一个集合中的数,用一个超级汇点链接第二个集合中的数,跑最短路即可。时间复杂度为:\(O(Tnlog^2n)\)。

但还有一个方法是:以那 \(k\) 个数为起点与终点,正着跑一次最短路,反着跑一次最短路,然后枚举边来判断最短路,其实就是上面讲的替换思想,只不过这里不是替换,而是枚举判断多源最短路。这里要注意最后枚举时要判断是否是环。

有向图通达性:强连通分量

P7737 [NOI2021] 庆典

本题有些毒瘤,但作为 noi T3 没有很难(主要难在实现了)。

先看部分分:

\(1 \sim 7\):暴力,每次都建一次图,从起点终点正图反图跑两次拓扑排序求并,时间复杂度:\(O(nq)\)。

先看 \(k=0\) 这个特殊条件:

有一个特殊性质是:\(m=n-1\),说明是有向树。当 \(k=0\) 时判断起点终点是否可以到达,深度相减就可以了。

如果没有特殊性质,就要用 tarjan 缩点了。

这时 $ x⇒y $的充要条件就是 \(y\) 在 \(x\) 的子树内,这一点可以用树剖 \(O(1)\) 判断。同时,我们可以前缀和求出每一段重路径上点的 size 之和,即为每一个的答案。

\(k>0\) 时:

先关注题目上的一个特殊条件:对于三座城市 \(x\),\(y\),\(z\),若 \(x⇒z\) 且 \(y⇒z\),那么有 \(x⇒y\) 或 \(y⇒x\)。

手动画图可发现:有些边是多余的。

把除红边都删除不影响连通性,可以拓扑排序只留下最后一条边,这样就变成了一课有向树。

然后 bfs ,先看是否可以到达,在把所有可通达路径加入树剖,然后路径取并集,再前缀和求个数即可。

每条路径搜索的上限大概是 \(4 \sim 6\) 次。

欧拉图

一些定理:

  1. 对于一个无向图 \(G\) 可以一笔画成的充要条件是: \(G\) 是联通的,并且奇顶点个数等于 \(0\) 或 \(2\)。当且仅当奇顶点个数为 \(0\) 时,\(G\) 是一个圈。

  2. 如果无向连通图有 \(G\) 有 \(2k\) 个奇顶点,则图 \(G\) 可以用 \(k\) 笔画成,并且至少要用 \(k\) 笔画成。

  3. 有向图 \(G\) 是欧拉图,当且仅当 \(G\) 弱连通且 \(G\) 的每个点的入度等于出度,有向图 \(G\) 是半欧拉图,当且仅当 \(G\) 弱连通,存在两个点的入度分别等于出度减 \(1\) 和出度加 \(1\),且其余每个点的入度等于出度。

例题:

! P1341 无序字母对

差分约束

*出纳员问题

注:此题解法全部引用冯威的集训队论文的文字,有兴趣观看全文。

设 \(num[ i ]\) 为 \(i\) 时刻能够开始工作的人数,\(x[ i ]\) 为实际雇佣的人数,那么 $ x[ I ]<=num[ I ]$ 。
设 \(r[ i ]\) 为 \(i\) 时刻至少需要工作的人数,于是有如下关系:

\[ x[ I-7 ]+x[ I-6 ]+x[ I-5 ]+x[ I-4 ]+x[ I-3 ]+x[ I-2 ]+x[ I-1 ]+x[ I ]>=r[ I ] \]

设 \(s[ I ]=x[ 1 ]+x[ 2 ]…+x[ I ]\) ,得到

\[ 0<=s[ I ]-s[ I-1 ]<=num[ I ], 0<=I<=23 \]

\[ s[ I ]-s[ I-8 ]>=r[ I ], 8<=I<=23 \]

\[ s[ 23 ]+s[ I ]-s[ I+16 ]>=r[ I ], 0<=I<=7 \]

对于以上的几组不等式,我们采用一种非常笨拙的办法处理这一系列的不等式(其实也是让零乱的式子变得更加整齐,易于处理)。首先我们要明白差分约束系统的应用对象(它通常针对多个二项相减的不等式的)于是我们将上面的所有式子都转化成两项未知项在左边,另外的常数项在右边,且中间用 \(\ge\) 连接的式子,即:

\[ s[ I ]-s[ I-1 ]>=0            (0<=I<=23) \]

\[ s[ I-1 ]-s[ I ]>=-num[ I ]       (0<=I<=23) \]

\[ s[ I ]-s[ I-8 ]>=r[ I ]         (8<=I<=23) \]

\[ s[ I ]-s[ I+16 ]>=r[ I ]-s[ 23 ]  (0<=I<= 7) \]

这里出现了小的困难,我们发现以上式子并不是标准的差分约束系统,因为在最后一个式子中出现了三个未知单位。但是注意到其中跟随 \(I\) 变化的只有两个,于是 \(s[23]\) 就变得特殊起来,看来是需要我们单独处理,于是我们把 \(s[ 23 ]\) 当作已知量放在右边。
经过这样的整理,整个图就很容易创建了,将所有形如 \(A-B>=C\) 的式子 我们从节点 \(B\) 引出一条有向边指向 \(A\)  边的权值为 \(C\)(这里注意由于左右确定,式子又是统一的>=的不等式,所以A和B是相对确定的,边是一定是指向 \(A\) 的),图就建成了 。
最后枚举所有 \(s[ 23 ]\) 的可能值,对于每一个 \(s[23]\) ,我们都进行一次常规差分约束系统问题的求解,判断这种情况是否可行,如果可行求出需要的最优值,记录到 \(Ans\) 中,最后的 \(Ans\) 的值即为所求。

标签:图论,23,int,短路,路径,好题,此题,式子
From: https://www.cnblogs.com/hutongzhou/p/18169023

相关文章

  • 好题——动态规划
    前言本文章将会持续更新,主要是一些个人觉得比较妙的题,主观性比较强(给自己记录用的),有讲错请补充。带!号的题是基础例题,带*号的是推荐首先完成的题(有一定启发性的)。动态规划线性动态规划!JuryCompromise(蓝书例题)看到题目比较容易的想到:定义:f[i][j][k]为\(i\)表示考......
  • 好题——数学与数据结构
    前言本文章将会持续更新,主要是一些个人觉得比较妙的题,主观性比较强(给自己记录用的),有讲错请补充。带!号的题是基础例题,带*号的是推荐首先完成的题(有一定启发性的)。组合数P6620[省选联考2020A卷]组合数问题运用斯特林数好的例题,普通幂转下降幂。用到第二类斯特林数。\[......
  • 24/04/27 图论及 dfs 序相关
    \(\color{green}(1)\)CF721CJourney给定一张\(n\)个点\(m\)条边的有向无环图,边有边权。构造一条\(1\ton\)的路径使得其边权和\(\lek\)且经过的点数最多。\(n,m\le5\times10^3\),\(k\le10^9\)。最简单的想法是设状态\(f_{i,j}\)表示\(1\toi\)的边权......
  • 24/04/25 图论
    \(\color{purple}(1)\)P5478[BJOI2015]骑士的旅行给定一颗\(n\)个节点的树。有\(m\)个骑士,最开始第\(i\)个骑士在\(p_i\)节点上,武力值为\(f_i\)。接下来有\(q\)次操作\((t_i,x_i,y_i)\):\(t_i=1\),输出树上\(x_i,y_i\)路径上的前\(k\)大骑士的武力值。......
  • (图论分析,思维)ABC 350-D
    背景:我自己思考想出来的图论题,总归是有成就感的分析:求间接连接的点的对数,即一个连通块中枚举出两两连接的组合数,减去整个连通块中的边数,因为一条边必然直接连接了两个不同的点原理:并查集时间复杂度:o(n)代码如下:点击查看代码#include<bits/stdc++.h>usingnamesp......
  • 【图论】最短路练习——P1629邮递员送信
    邮递员送信题目描述有一个邮递员要送东西,邮局在节点\(1\)。他总共要送\(n-1\)样东西,其目的地分别是节点\(2\)到节点\(n\)。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有\(m\)条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完......
  • 图论理论基础
    Smiling&Weeping ----前方的风景好像很美...图论基础总结图论是研究图的结构和性质的数学分支。图是一种由节点(顶点)和边组成的数学结构,其中节点表示实体,边表示实体之间的关系。图论可以应用于解决许多现实世界中的问题,例如社交网络分析、交通......
  • 又一道好题
    题目链接戳我\(Solution\)维护一个上升的序列,对于一个操作把\(x+1\),不会使得这个序列下降,对于操作1,假设x下标位置的值是\(a\),把他和最右边数值为\(a\)的点交换一个位置再\(+1\)同样也不会影响这个序列的单调性。所以搞一个树状数组区间加单点查询即可,对于交换操作记录一下原序......
  • [学习笔记] 树上差分 - 图论
    前置知识:树,LCA,前缀和与差分边差分这个名字是在网上看到的,不理解为什么要叫这么一个名字,可能是因为它与树链修改有关。当然,用于树链修改单点查询非常方便~看这个图,该图是以点1为根进行DFS的。如果我们要把从3->4这条树链上所有的点统统加上1,可以都转化为对到根节点的......
  • [学习笔记] LCA - 图论
    [NOIP2013提高组]货车运输最大生成树+LCA+倍增好家伙,这道题我写了一个晚上,调了两个晚上,对于这道题我颇有感触。但这道题确实好,实实在在的蓝题,让我发现了许多关于LCA的问题。首先,这个题给的是一个无向图,并不是个树,为了减少运算量,我们可以把它变成一个树。运用Kruskal算法生......