【题意】
图中有N个点,M条边,求1到N的最短时间。保证有解。
N<=100,M<=10000
【分析】
很裸的最短路,但是也好长时间没有打Dijkstra了,而且之前也没有打过+优先队列的,在这里试试,然后WA了好几发。。。。
最后发现优先队列更新的时候d[x]打成了p[i].v
仔细想想,dijkstra本身的思想就是维护两个集合,第一组为已求出最短路径的顶点集合(用S表示),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把U中的顶点加入S中。
【Code】
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
typedef long long LL;
#define INF 0x3f3f3f3f
const int MAX_N = 10000 + 10;
const int MAX_M = 40000 + 10;
int d[MAX_N], head[MAX_N];
bool v[MAX_N];
int n, m, cnt;
struct edge{
int from, to, v, next;
} p[MAX_M];
struct node{
int num, val;
bool operator <(const node &c)const {
return val > c.val;
}
};
void add(int u, int v, int w)
{
p[cnt].from = u;
p[cnt].to = v;
p[cnt].v = w;
p[cnt].next = head[u];
head[u] = cnt++;
}
void dijkstra(int s)
{
for (int i=1;i<=n;i++) d[i] = INF;
memset(v,0,sizeof(v));
priority_queue<node> pq;
while (!pq.empty()) pq.pop();
d[s] = 0;
node t;
pq.push((node){s,0});
while (!pq.empty()){
t = pq.top();
pq.pop();
int u = t.num;
if (v[u]) continue;
v[u] = true;
for (int i=head[u];i!=-1;i=p[i].next){
int x = p[i].to;
if (d[x] > d[u] + p[i].v){
d[x] = d[u] + p[i].v;
pq.push((node){x,d[x]});
}
}
}
}
int main()
{
int x, y, z;
while (~scanf("%d%d",&n,&m)&&n){
memset(head,-1,sizeof(head));
cnt = 0;
for (int i=0;i<m;i++){
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
dijkstra(1);
printf("%d\n",d[n]);
}
}