专栏文章

链式前向星

个人记录参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@mip2q7wq
此快照首次捕获于
2025/12/03 05:12
3 个月前
此快照最后确认于
2025/12/03 05:12
3 个月前
查看原文
今天写了一个必须使用链式前向星,并且需要建两张图的题,然后调试发现好几处不分边的编号和点的编号,不分第一张图和第二张图的错误。
引以为戒。
以下指出链式前向星正确的使用方式:
CPP
struct Graph{
	struct Edge{int from,to,pre,nxt;}e[maxn*2];
	int h[maxn],edge_cnt=1;
	
	void add(int x,int y){
		e[++edge_cnt]={x,y,0,h[x]};
		e[h[x]].pre=edge_cnt;
		h[x]=edge_cnt;
	}

	void del(int id){
		e[e[id].pre].nxt=e[id].nxt;
		e[e[id].nxt].pre=e[id].pre;
		if(h[e[id].from]==id) h[e[id].from]=e[id].nxt;
	}
	
	template<typename T>
	void for_each(int u,T func){
		for(int eid=h[u];eid;eid=e[eid].nxt) func(e[eid].to,eid);
	}
}g1,g2;
使用(遍历所有 u 到 i 的,编号为 e 的边):
CPP
g1.for_each(u,[&](int i,int e){
    // do something
});
不需要编号时可以这么写:
CPP
g1.for_each(u,[&](int i,int){
    // do something
});
既然这样,不如附上这题题解:
显然答案为 max{a×disi,b×disi2+a×(disimod2),b×evendisi}\max\{a\times dis_i,b \times \lfloor{dis_i\over 2}\rfloor+a\times (dis_i \bmod 2),b \times evendis_i\}
其中 evendisevendis 表示只走 bb 边的最短路。
考虑跑最短路。我们要解决的问题是:有两组点 ai,bia_i,b_i,有若干个(设为 kk 个)表示不能走的边 (au,bv)(a_u,b_v),我们需要在 dijkstra 时从 aa 更新到 bb。我们希望复杂度与 kk 有关。
可以使用数据结构(类似可持久化线段树)暴力优化建图。但我们有更巧妙的做法:
还是考虑原图上这个问题的形式:aixbia_i\to x\to b_i。此时,如果 xbix\to b_i 被访问过,则再次访问一定不会带来更好的更新。所有我们可以直接删掉。复杂度是 O(k)O(k)
考虑这张图中这个结构的总和。发现是三元环的个数,为 O(nn)O(n\sqrt n)。可以通过本题。

评论

1 条评论,欢迎与作者交流。

正在加载评论...