gogododone @ 2023-02-05 20:55:25
使用的是优先队列,但是 #2 #3 #6 case 超时了。。。
有大佬能帮忙分析下哪里耗时了嘛?
感谢感谢~~
代码如下:
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
#define MAXN 500001
#define INF ((1<<31)-1)
int VERTEX;
int EDGE;
struct Edge
{
int to, w, next;
};
Edge edges[MAXN];
int head[MAXN], cnt;
void addEdge(int from, int to, int w)
{
edges[++cnt].to = to;
edges[cnt].w = w;
edges[cnt].next = head[from];
head[from] = cnt;
}
void dijkstra(int start, vector<int>& dist)
{
dist[start] = 0;
vector<int> visited(VERTEX+1, 0);
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> _q;
_q.push({dist[start],start});
while (!_q.empty())
{
int minDist = _q.top().first;
int from = _q.top().second;
_q.pop();
visited[from] = 1;
for (int e=head[from]; e; e=edges[e].next)
{
int to = edges[e].to;
int w = edges[e].w;
if (!visited[to] && dist[to] > dist[from] + w)
{
dist[to] = dist[from] + w;
_q.push({dist[to], to});
}
}
}
}
int main()
{
int start;
scanf("%d%d%d", &VERTEX, &EDGE, &start);
for (int i=1; i<=EDGE; i++)
{
int from, to, w;
scanf("%d%d%d", &from, &to, &w);
addEdge(from, to, w);
}
vector<int> dist(VERTEX+1, INF);
dijkstra(start, dist);
for (int i=1; i<=VERTEX; i++)
printf("%d ", dist[i]);
printf("\n");
return 0;
}
by Lysea @ 2023-02-05 21:11:52
@gogododone 将visited[from] = 1;
前面加一句if(visited[from]) continue;
,if (!visited[to] && dist[to] > dist[from] + w)
可以改成if (dist[to] > dist[from] + w)
。
by gogododone @ 2023-02-05 21:45:00
@Sands_Of_Time 非常感谢解答!!这种改法的确可以全部 AC。
但是我还是比较疑惑,这样写快的原因在哪里?
按照我的写法,我每次加入到队列中的顶点,都是没有被收录过的。
所以每次 from=_q.top().second; 时, if (visited[from]) 应该都是 false 才对呀。
希望有空的话再指教一下,感谢感谢!!
by gogododone @ 2023-02-06 20:40:10
我找到原因了,因为一个顶点可能会被多次加入队列中。 我们只需要处理第一次加入的那个节点,后续的可以直接跳过。
我把这个和 SPFA 中搞混了。