求卡常
查看原帖
求卡常
766573
chenbs楼主2024/10/1 19:13

使用了 spfa + 带修改的优先队列,避免了 MLE 的情况,然而 TLE on #12(前 11 个点都跑的很快,全部小于0.2s)

#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 v, w;
} e[200005]; // 储存不经过规定路线的边
int h[200005];
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-1]; i<h[x]; i++) {
			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)
			h[all[i].u+1]++;
	for(int i=1; i<=n; i++) h[i]+=h[i-1];
	for(int i=1; i<=m; i++)
		if(!all[i].f)
			e[h[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 19:13
加载中...