OI中用priority_queue替代set的一些小trick

set由于其功能强大,令人爱不释手。

但是换来的是令人作呕的常数。

其实在一些简单的操作中,set是可以用priority_queue来替代的,后者常数小,代码相对来说也要简洁一些。

堆优化dij的priority_queue写法:

*SPFA已死,有事烧纸

正常的堆写法是需要删除的,显然set是可以做到这一点的,需要用pair,很烦。

问题1:

c++优先队列默认是大顶堆,我们需要取出的是距离最小的。

解决:

如果不写那些骚到不行的c++语法,最好用的方法就是结构体+重载了。

不用担心重载的常数问题,经过实测这个是几乎可以忽略滴。

问题2:

c++优先队列不支持删除,然而我们在更新最短距离后需要删除原来的。

解决:

这个采取懒惰删除法。

我们在取出堆顶后,判断它是否已经被确定了最短路,如果已经被确定了,说明它是懒惰删除没有删除的,pop()后继续取即可。

struct nod {
	ll s; int x;
} a[N];
bool operator <(nod a, nod b) {return a.s > b.s;}
priority_queue<nod> q;
//...
while(!q.empty()) {
		nod b = q.top(); q.pop(); int x = b.x;
		if(bz[x]) continue; bz[x] = 1;
		for(int i = fi[x]; i; i = nt[i]) if(b.s + v[i] < a[to[i]].s)
			a[to[i]].s = b.s + v[i], q.push(a[to[i]]);
}

带删除的堆:

由于dij的特殊性,我们可以通过是否确定了最短路来判断这个堆顶应不应该删除。

但是对于所有堆这显然不行,一个有意思的trick是再开一个删除堆,每次两个堆的堆顶,如果相等,则同时pop()

大概是这么写:

struct head {
	priority_queue<int> a, b;
	void ins(int x) { a.push(x);}
	void del(int x) { b.push(x);}
	void pop()	{
		while(b.size() && a.top() == b.top())
			a.pop(), b.pop();
		a.pop();
	}
	int top() {
		while(b.size() && a.top() == b.top())
			a.pop(), b.pop();
		return a.top();
	}
	int size() {return a.size() - b.size();}
	int stop() { //second maximum 
		int x = top(); pop();
		int y = top(); ins(x);
		return y;
	}
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值