图结构练习——最短路径
Problem Description
给定一个带权无向图,求节点1到节点n的最短路径。
Input
输入包含多组数据,格式如下。
第一行包括两个整数n m,代表节点个数和边的个数。(n<=100)
剩下m行每行3个正整数a b c,代表节点a和节点b之间有一条边,权值为c。
Output
每组输出占一行,仅输出从1到n的最短路径权值。(保证最短路径存在)
Sample Input
3 2
1 2 1
1 3 1
1 0
Sample Output
1
0
注意:此代码用于稀疏图,或者节点数很多二维数组存不下。在稠密图中可以继续使用邻接矩阵。
代码:
#include <iostream>
#include <stdio.h>
#include <queue>
#include <cstring>
#define inf 0x3f3f3f
using namespace std;
typedef struct node { // 定义优先队列
int v,date;
} ty;
bool operator < ( const ty &a, const ty &b ) // 定义优先队列
{
return a.date>b.date;
}
struct edge { // 存邻接表的边
int v,w,next;
} a[100005];
int head[105];
int dis[105];
int via[105];
int cnt;
int n,m;
ty t,d;
void dijkstra( int v0 ) // 堆优化的dijkstra + 邻接表
{
priority_queue <ty> Q;
memset(dis,inf,sizeof(dis));
dis[v0] = 0;
t.v = v0;
t.date = 0;
Q.push(t);
while ( !Q.empty() ) {
if ( via[Q.top().v]==1 ) {
Q.pop();
continue ;
}
t = Q.top();
Q.pop();
int u = t.v;
dis[u] = t.date;
via[u] = 1;
for ( int i=head[u]; i!=-1; i=a[i].next ) { // 这块代码容易出错,好好看
int j = a[i].v; // 通过邻接表直接找相邻的点
if ( via[j]==0 && dis[j]>dis[u]+a[i].w ) {
dis[j] = dis[u]+a[i].w;
d.v = j;
d.date = dis[j];
Q.push(d);
}
}
}
cout << dis[n] << endl;
}
int main()
{
while ( cin >> n >> m ) {
cnt = 0;
memset(head,-1,sizeof(head));
memset(via,0,sizeof(via));
for ( int i=0; i<m; i++ ) {
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
a[cnt].v = y; // 无向图
a[cnt].w = z;
a[cnt].next = head[x];
head[x] = cnt++;
a[cnt].v = x; // 正反存两次
a[cnt].w = z;
a[cnt].next = head[y];
head[y] = cnt ++;
}
dijkstra(1);
}
return 0;
}