最短路Dijkstra的模板题,不过需要注意的是,这道题的图是无向图。
用了两种方式过这道题,一种是基本的方式,一种是借助优先队列优化的。
第一种代码:(要用邻接矩阵)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define inf 10000005
using namespace std;
const int maxn=1e3+5;
int map[2*maxn][2*maxn],dis[2*maxn];
bool vis[2*maxn];
void dijkstra(int n) //用邻接矩阵进行操作的dijkstra,时间复杂度为O(n^2),其原理与最小生成树Prim算法很相似
{
for(int i=1;i<=n;i++) //初始化,起点设为1
{
dis[i]=map[1][i];
vis[i]=0;
}
vis[1]=1; //vis[i]=1表示顶点i已经更新过了
for(int i=1;i<=n;i++)
{
int temp=inf,k=0;
for(int j=1;j<=n;j++)
if(!vis[j]&&dis[j]<temp)
temp=dis[k=j];
if(temp==inf) break;
vis[k]=1;
for(int j=1;j<=n;j++) //dijkstra与Prim不同的地方就在这里,更新的方式不同罢了
dis[j]=min(dis[j],dis[k]+map[k][j]); //源点1到j的最小距离是无通过k点和通过k点两者之间的最小值
}
}
int main()
{
int n,T;
scanf("%d%d",&T,&n); //注意输入的顺序
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j) map[i][j]=inf;
else map[i][j]=0;
for(int i=1;i<=T;i++)
{
int u,v,cost;
scanf("%d%d%d",&u,&v,&cost);
map[u][v]=map[v][u]=min(map[u][v],cost); //注意,是两者之间的最小值
}
dijkstra(n);
printf("%d\n",dis[n]);
return 0;
}
第二种方式:(用邻接矩阵)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#define inf 10000005
using namespace std;
const int maxn=1e3+5;
struct road
{
int cost,v;
bool operator < (const road& a) const //重置运算符“<”,使优先队列能够按cost从小到大排序
{
return cost>a.cost;
}
};
vector<road> G[maxn]; //建立邻接链表
int dis[maxn]; //dis记录从顶点1开始到其他所有顶点的最短路径
bool vis[maxn]; //vis标志顶点i是否被更新过
void dijkstra(int n) //用优先队列优化的dijkstra,时间复杂度为O(ElogE)
{
priority_queue<road> Q;
for(int i=1;i<=n;i++) //初始化
{
dis[i]=inf;
vis[i]=0;
}
dis[1]=0;
road u;
u.v=1; u.cost=0;
Q.push((u));
//Q.push( (road){0,1} ); //采用这种方法插入会使代码更加好看,可惜提交的时候CE了,就没采用
while(!Q.empty())
{
road top=Q.top(); Q.pop(); //取出队列队首,即边权最短的元素,并将其弹出队列
int v=top.v; //取其终点
if(vis[v]) continue; //如果这个顶点已经被更新过,则继续下次循环,否则更新以它为起点的边
vis[v]=1;
for(int i=0;i<G[v].size();i++)
{
road r=G[v][i]; //取出边
if(dis[r.v]>dis[v]+r.cost) //如果原本从1到终点r.v的值dis[r.v]大于从1到v再到终点r.v的值,则更新dis[r.v]以及队列
{
dis[r.v]=dis[v]+r.cost;
road k;
k.v=r.v; k.cost=dis[r.v];
Q.push(k);
//Q.push( (road){dis[r.v],r.v} );
}
}
}
}
int main()
{
int n,T;
scanf("%d%d",&T,&n);
for(int i=1;i<=T;i++)
{
int u; road a;
scanf("%d%d%d",&u,&a.v,&a.cost);
G[u].push_back(a);
swap(a.v,u);
G[u].push_back(a); //记得这是个无向图
}
dijkstra(n);
printf("%d\n",dis[n]);
return 0;
}
好几次提交的时候RE了。。。因为输入的顺序是T,N,而不是N,T,一开始反了过来就错了。。。要注意