【学弟向】图的存储与遍历,最短路,连通性 tarjan,树状数组

学弟向,大佬们别喷。

树状数组

单点修改,前缀查询。

int lbd(int x) {return (x&(-x));}
void gai(int x,int c) {for(int i=x;i<=n;i+=lbd(i)) a[i]+=c;}
int cha(int x) {int da=0;for(int i=x;i;i-=lbd(i)) da+=a[i];return da;}

上面这个模板同样是单点加/单点改/单点取max + 查前缀 max/查前缀和。

查询信息可减就可以直接查区间(两个前缀和减一下)。

优点是代码比线段树短。
什么?你想要更炫酷的序列操作?
哎不是你是不是为难学哥,不久有个讲线段树的学哥你去问他。

图的存储与遍历

链式前向星

const int QAQ=1001,ovo=QAQ*QAQ;
int cnt,head[QAQ],to[ovo],nex[ovo],bq[ovo];
void lian(int u,int v,int w)
{
	++cnt;
	to[cnt]=v;
	nex[cnt]=head[u];
	bq[cnt]=w;
	head[u]=cnt;
}
void dfs(int x,int dis)
{
	for(int i=head[x];i;i=nex[i])
	{
		int v=to[i],w=bq[i];
		dfs(v,dis+w);
	}
}

臭链表,我上了高一才明白这个存图,大家不理解可以用 vector。
如果你以后做到需要这种存图的题,那么那时候你再来学这个就很容易了,因为你做到需要找反向边的题说明那时候你已经有一些代码能力。
不过目前可以先不用理解这个。

vector

const int QAQ=1001;
vector<int> dian[QAQ],bian[QAQ];
void lian(int u,int v,int w)
{
	dian[u].push_back(v);
	bian[u].push_back(w);
}
void dfs(int x,int dis)
{
	for(int i=0;i<dian[x].size();i++)
	{
		int v=dian[x][i],w=bian[x][i];
		dfs(v,dis+w);
	}
}

最好理解的存图。

最短路

听说大家学过了。
单源最短路 dij、spfa。
多源最短路学弗洛伊德。
这仨够用了,其他的我也没写过。

感觉上
dij 像贪心。
spfa 像乱搞。
弗洛伊德 像 DP。

多源不考虑复杂度时选弗洛伊德。
没负边权选 dij,否则选 spfa。

是不是要给学弟们讲个题???
第一题
第二题
spfa 判负环

连通性 tarjan

这里的连通性并非并查集之类的,把那些东西收起来!

强连通:有向图中任意两个点连通(互相走到)。
强连通分量:极大的强连通子图。(理解一下极大:能括就括,强连通分量的子图不是强连通分量)

感觉更好理解的说法是:强连通子图。

找强连通分量

(注意别忘了我们在有向图

因为强连通分量任意两个点能互相走到,所以我们直接从一个点开始 dfs,可以构成一个 dfs 树。

posted @ 2025-11-08 18:00  _a1a2a3a4a5  阅读(3)  评论(0)    收藏  举报