简单地复习下最短路
SparkKnight · · 个人记录
最短路,比赛中最常用的就是迪杰斯特拉再加上亿一点点优化
实际上,所有最短路算法的基本思路就是绕近路:能找到一个点C,使得A→C→B的距离小于A→B,然后重复。
而这个C点怎么找,仁者见仁智者见智。你可以所有的点都找一遍:随便找三个点ABC,看看是否满足上面的规律,然后重复直到所有可能的点的组合都看过一遍。当然这是Floyd的思路,虽然有高达O(N^3)的复杂度,但它非常好写:
//P1529 [USACO2.4]回家 Bessie Come Home
#include <bits/stdc++.h>
using namespace std;
#define inf 114514
#define MAXN 55
int Map[MAXN][MAXN],int n;
int ctoI(char c){return c>96?c-70:c-64;}
char itoC(int c){return c>26?c+70:c+64;}
int main()
{
for(int i=0;i<MAXN;i++){for(int j=0;j<MAXN;j++){Map[i][j]=inf;if(i==j){Map[i][j]=0;}}}
cin>>n;
for(int i=1,weight;i<=n;i++)
{
char a,b;
cin>>a>>b>>weight;
//cout<<ctoI(a)<<" "<<ctoI(b)<<endl;
Map[ctoI(a)][ctoI(b)]=min(weight,Map[ctoI(a)][ctoI(b)]);
Map[ctoI(b)][ctoI(a)]=min(weight,Map[ctoI(b)][ctoI(a)]);
}
for(int k=0;k<MAXN;k++)
{
for(int i=0;i<MAXN;i++)
{
for(int j=0;j<MAXN;j++)
{
Map[i][j]=min(Map[i][j],Map[k][j]+Map[i][k]);
}
}
}
int minC,minD=inf;
for(int i=0;i<=25;i++)
{
if(minD>Map[i][26])
{
minD=Map[i][26];
minC=i;
}
}
cout<<itoC(minC)<<" "<<minD<<endl;
return 0;
}
而迪杰斯特拉虽然有些复杂该死的邻接表什么鬼啊,但它的时间复杂度较低,优化后可达到O(E*logV),其中E为边的数量,V为顶点的数量。
关于迪杰斯特拉的思路,就是维护一个集合一个数组。一个集合就是已找到最短路径的点的集合,数组就是代码里的dis数组。
下面就是一份迪杰斯特拉+堆优化+邻接表的模板:
#include <bits/stdc++.h>
using namespace std;
#define inf 2147483647
#define MAXL 200005
#define int long long
/*存图部分*/
struct EDGE
{
int next, to, weight;
//next:与这条边起点相同的上一条边的编号
//to:指向节点编号
//weight:边权值
} edge[MAXL];
int head[MAXL], cnt = 0;
void addEdge(int u, int v, int w)
{
edge[++cnt].next = head[u];
edge[cnt].to = v;
edge[cnt].weight = w;
head[u] = cnt;
}
int n,m,s;//n:几个点 m:几条边 s:出发点
/*堆优化部分*/
struct node
{
int ans;//该点对应的dis值
int id;//该点对应的编号
bool operator<(const node &x)const
{
return x.ans<ans;
}
};
priority_queue<node> q;
int dis[MAXL];
bool visited[MAXL];
void dijkstra2(int s)
{
for (int j = 1; j <= n; j++)
{
dis[j]= inf;
visited[j] = false;
}
dis[s] = 0;
q.push((node){0,s});
int pos=s;
while(!q.empty())
{
node minP=q.top();
q.pop();
if(!visited[minP.id])
{
visited[minP.id]=1;
for(int i=head[minP.id];i!=0;i=edge[i].next)
{
if(dis[minP.id]+edge[i].weight<dis[edge[i].to])
{
dis[edge[i].to]=dis[minP.id]+edge[i].weight;
q.push((node){dis[edge[i].to],edge[i].to
});
}
}
}
}
}