codeforces 20 c 堆优化dijkstra + 路径打印

题目:

C. Dijkstra?
time limit per test
1 second
memory limit per test
64 megabytes
input
standard input
output
standard output

You are given a weighted undirected graph. The vertices are enumerated from 1 to n. Your task is to find the shortest path between the vertex 1 and the vertex n.

Input

The first line contains two integers n and m (2 ≤ n ≤ 105, 0 ≤ m ≤ 105), where n is the number of vertices and m is the number of edges. Following m lines contain one edge each in form aibi and wi (1 ≤ ai, bi ≤ n, 1 ≤ wi ≤ 106), where ai, bi are edge endpoints and wi is the length of the edge.

It is possible that the graph has loops and multiple edges between pair of vertices.

Output

Write the only integer -1 in case of no path. Write the shortest path in opposite case. If there are many solutions, print any of them.

Examples
input
5 6
1 2 2
2 5 5
2 3 4
1 4 1
4 3 3
3 5 1
output
1 4 3 5 
input
5 6
1 2 2
2 5 5
2 3 4
1 4 1
4 3 3
3 5 1
output
1 4 3 5 


代码:

尽管图中可能有自环和多重边,但不会出现负环,因此dijkstra依然可用 负环需要使用Bellman-Ford

实现的时候有几个细节需要留心:

起始点到某些结点的最小距离会超出int范围;

memset()和fill()不要混用,使用fill()时第二个参数的含义是连续多少个空间进行初始化,所以从0开始的时候需要写成n+1


#include<bits/stdc++.h>
#include<queue>
using namespace std;
const int maxn=1e5+30;
const __int64 inf=(__int64)1<<62;//0x3f3f3f3f 太小了.... 

typedef pair<__int64,int> p;//<a,b> 起点到b的最短距离为a 

struct edge {
	int to;
	int cost;
	edge(int tto=0,int ccost=0):to(tto),cost(ccost){}
};

int n,m;
__int64 d[maxn];
int prev[maxn];
vector<edge> g[maxn];

void dijkstra(int s) {
	priority_queue<p,vector<p>,greater<p> >qu;//堆按照p的first(最短距离)排序,小顶堆 
	fill(d,d+n+1,inf);
	fill(prev,prev+n+1,-1);//+n 太小了... 
//	memset(prev,sizeof(prev),-1);//混用会报错 
	d[s]=0;
	qu.push(p(0,s));//从起点出发到顶点s的最短距离为0
	while(!qu.empty()) {
		p temp=qu.top();
		qu.pop();
		int tmpv=temp.second;
		if(temp.first>d[tmpv]) continue;//跳过更新过程中入队的非最小值 
		for(int i=0;i<g[tmpv].size();++i) {//遍历该顶点连出的每条边 
			edge e=g[tmpv][i];
			if(d[e.to]>d[tmpv]+e.cost) {
				d[e.to]=d[tmpv]+(__int64)e.cost;
				prev[e.to]=tmpv;
				qu.push(p(d[e.to],e.to));
				
			}
		}
	}
}

vector<int> getpath(int t) {//s -> t
	vector<int> path;
	while(t!=-1) {//从 t 倒着走,一直走到 s 
		path.push_back(t);
		t=prev[t];
	}
	reverse(path.begin(),path.end());
	return path;
}

int main() {//78ms 6400kb
	int a,b,c;
	scanf("%d%d",&n,&m);
	for(int i=0;i<=n;++i) {
		g[i].clear();
	}
	for(int i=1;i<=m;++i) {
		scanf("%d%d%d",&a,&b,&c);
		g[a].push_back(edge(b,c));
		g[b].push_back(edge(a,c));
	}
	dijkstra(1);
	if(d[n] == inf) puts("-1");
	else {
		vector<int> pt = getpath(n);
		vector<int>::iterator it=pt.begin();
		printf("%d",*it);
		++it;
		for(; it!=pt.end(); it++) printf(" %d",*it);
		puts("");
	}
	return 0;
}

或者一开始d[]初始化为-1,第34行改为if((d[e.to]>d[tmpv]+e.cost)||d[e.to]==-1),第66行改为if(d[n] == -1) puts("-1");,也可以。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值