您的位置:首页 > 其它

CodeForces 20C Dijkstra? (最短路)

2014-04-15 20:06 537 查看
题目类型 图论 - 最短路

题目意思
给出一个最多包含 1e5 个点和 1e5 条边的图, 求1 -> n的最短路是多少

解题方法

最短路是一个经典的问题

还没掌握

Dijkstra算法 & Bellman-Ford算法 & SPFA & Floyd算法

这几种最短路算法的同学 猛戳 -> 最短路算法(Shortest Paths Algorithm)(几种算法的原理+代码)

注意

由于这道题的点和边的大小都达到了1e5,所以推荐使用 用堆优化过的Dijkstra算法 或 SPFA

用一个一维辅助数组int pre[MAXN]即可记录路径, 当一个点u可以用 dist[u] + edge(u, v) 更新 dist[v]时, pre[v] = u

参考代码 - 有疑问的地方在下方留言 看到会尽快回复的

优先队列+Dijkstra

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>

using namespace std;

typedef long long LL;

const int MAXN = 1e5 + 10;
const LL INF = 1LL<<62;
vector<int>e[MAXN];
vector<int>w[MAXN];
bool vis[MAXN];
LL d[MAXN];
int pre[MAXN];
int n;

struct Node {
LL d;
int u;
bool operator < (const Node & rhs) const {
return d > rhs.d;
}
};

void Dijkstra() {
priority_queue<Node>q;
for( int i=1; i<=n; i++ ) d[i] = INF;
d[1] = 0;
memset(vis, 0, sizeof(vis));
Node tn;
tn.d = 0, tn.u = 1;
q.push(tn);
while(!q.empty()) {
Node t = q.top(); q.pop();
int u = t.u;
if(vis[u]) continue;
vis[u] = true;
for( int i=0; i<e[u].size(); i++ ) {
int v = e[u][i];
if(d[v] > d[u] + w[u][i]) {
d[v] = d[u] + w[u][i];
pre[v] = u;
tn.d = d[v], tn.u = v;
q.push(tn);
}
}
}
}

int main() {
int m;
while(scanf("%d%d", &n, &m) != EOF) {
for( int i=1; i<=n; i++ ) e[i].clear(), w[i].clear();
int a, b, c;
for( int i=0; i<m; i++ ) {
scanf("%d%d%d", &a, &b, &c);
e[a].push_back(b); w[a].push_back(c);
e[b].push_back(a); w[b].push_back(c);
}
Dijkstra();
if(d
== INF) printf("-1\n");
else {
e[1].clear();
e[1].push_back(n);
while(pre
!= 1) {
n = pre
;
e[1].push_back(n);
}
e[1].push_back(1);
for( int i=e[1].size()-1; i>0; i-- ) printf("%d ", e[1][i]);
printf("%d\n", e[1][0]);
}
}
return 0;
}
SPFA - 注意用 vector 构造邻接表可能会导致超时, 所以可以用数组的方式构造邻接表, 不会的同学猛戳 -> ACM中关于图的邻接表的表示方法

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>

using namespace std;

typedef long long LL;

const int MAXN = 1e5 + 10;
const LL INF = 1LL<<62;
bool vis[MAXN];
LL d[MAXN];
int pre[MAXN];
int n;
int fa[MAXN];
int cnt;
int n_res[MAXN];
struct P {
int u, v, w;
}node[MAXN*3];

bool SPFA() {
memset(vis, 0, sizeof(vis));
queue<int>q;
q.push(1);
for( int i=1; i<=n; i++ ) d[i] = INF;
d[1] = 0;
vis[1] = 1;
while(!q.empty()) {
int f = q.front();
q.pop();
vis[f] = 0;
for( int i=fa[f]; i!=-1; i=node[i].u ) {
int v = node[i].v;
if(d[v] > d[f] + node[i].w) {
d[v] = d[f] + node[i].w;
pre[v] = f;
if(vis[v] == 0) {
vis[v] = 1;
q.push(v);
//printf("push %d\n", v);
}
}
}
}
return true;
}

int main() {
int m;
while(scanf("%d%d", &n, &m) != EOF) {
memset(fa, -1, sizeof(fa));
int a, b, c;
for( int i=0; i<m; i++ ) {
scanf("%d%d%d", &a, &b, &c);
node[cnt].u = fa[a];
node[cnt].v = b;
node[cnt].w = c;
fa[a] = cnt++;
node[cnt].u = fa[b];
node[cnt].v = a;
node[cnt].w = c;
fa[b] = cnt++;
}
SPFA();
if(d
== INF) printf("-1\n");
else {
int k = 0;
n_res[k++] = n;
while(pre
!= 1) {
n = pre
;
n_res[k++] = n;
}
n_res[k++] = 1;
for( int i=k-1; i>0; i-- ) printf("%d ", n_res[i]);
printf("%d\n", n_res[0]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: