TLE on #12
查看原帖
TLE on #12
766573
chenbs楼主2024/10/1 08:48

spfa,使用了支持修改的优先队列,防止 MLE。我试了一下,本地跑 hack 数据大约需要 20 秒,不知道有没有优化的方法。

#include<bits/stdc++.h>
#include<bits/extc++.h>
using namespace __gnu_pbds;
struct Edge {
	int u, v, w;
	int f; // 是否在最短路上
} all[200005]; // 储存所有边
struct Edge2 {
	int u, v, w;
	int ne;
} e[200005]; // 储存不经过规定路线的边
int h[100005], idx;
void add(int u, int v, int w) {
	e[++idx] = {u, v, w, h[u]};
	h[u] = idx;
}
struct node {
	int u, dis;
	bool operator < (const node &x) const {
		return dis > x.dis;
	}
};
priority_queue<node>s;
priority_queue<node>::point_iterator tmp[100005];
int tmpf[100005];
int n, m, l, dis[100005], disn[200005];
int q[100005], qh, qt;
int vis[100005];
int a[200005]; // 最短路的第 i 条边的索引
int pid[100005]; // 第 i 个点在最短路上的编号
void spfa(int st) {
	q[0]=st, qh=-1, qt=0; // (qh, qt]
	while(qh != qt) {
		++qh;
		if(qh>100000) qh=0;
		int x=q[qh];
		
//		if(q[qh+1] > q[qt]) std::swap(q[qh+1], q[qt]); // swap 玄学优化
		
		vis[x]=0;
		for(int i=h[x]; i; i=e[i].ne) {
			int y=e[i].v;
			if(dis[x]+e[i].w < dis[y]) {
				dis[y] = dis[x]+e[i].w;
				if(pid[y]) {
					if(tmpf[pid[y]]) {
						// 直接修改,防止 MLE
						s.modify(tmp[pid[y]], {pid[y], dis[y]+disn[pid[y]]});
					} else {
						tmp[pid[y]] = s.push({pid[y], dis[y]+disn[pid[y]]});
						tmpf[pid[y]]=1;
					}
				}
				if(!vis[y]) {
					vis[y]=1;
					++qt;
					if(qt>100000) qt=0;
					q[qt]=y;
					
//					if(q[qh+1] > q[qt]) std::swap(q[qh+1], q[qt]); // swap 玄学优化
				}
			}
		}
	}
}
int main() {
// 	freopen("hack.in", "r", stdin);
//	freopen("hack.out", "w", stdout);

	memset(dis, 0x3f, sizeof dis), dis[1]=0;
	scanf("%d%d%d", &n, &m, &l);
	for(int i=1; i<=m; i++) scanf("%d%d%d", &all[i].u, &all[i].v, &all[i].w);
	for(int i=1; i<=l; i++) scanf("%d", &a[i]), all[a[i]].f=1, pid[all[a[i]].v]=i+1;
	pid[all[a[1]].u]=1;

	for(int i=1; i<=m; i++)
		if(!all[i].f)
			add(all[i].u, all[i].v, all[i].w);

	for(int i=l; i; i--) disn[i]=disn[i+1]+all[a[i]].w;
	spfa(1);
	for(int i=1; i<=l; i++) {
		while(!s.empty() && s.top().u<=i) tmpf[s.top().u]=0, s.pop();
		printf("%d\n", s.empty()?-1:s.top().dis);
		dis[all[a[i]].v] = dis[all[a[i]].u] + all[a[i]].w;
		spfa(all[a[i]].v);
	}
//	printf("%d", clock());
	return 0;
}
2024/10/1 08:48
加载中...