Más corto algoritmo de ruta
Resumimos aquí sólo los más de dos algoritmo del camino más corto, el primero es: Dijkstra, y la segunda es: SPFA;
Ambos algoritmos utilizan la optimización de colas, Dijkstra es una cola de prioridad, es SPFA cola normal;
Dijkstra
Presentado por primera vez en primer lugar, y el más utilizado del algoritmo del camino más corto: Dijkstra;
Idea de este algoritmo se basa en un determinado punto de partida de s, s para encontrar el punto de este punto se puede conectar, se puede actualizar la ruta que conecta los puntos, y luego en el interior de cola de prioridad; cola de prioridad mantiene dos cosas, una este es el punto de partida s a punto peso camino, la etiqueta es un punto;
El enfoque aquí decir que es correcto para el lado negativo del proceso, por un lado negativo derecha, Dijkstra no se procesa,
Por ejemplo:
1-2 en peso de 1
2-3 valor de peso de -3
3-1 con un peso de 2
El Dijkstra cada punto atravesada sólo una vez, por lo que el camino más corto es de 1-2 1, en lugar de 1; cada borde por supuesto asegurarse de que el pie más corta sólo una vez;
plantilla de Dijkstra:
struct queue_element
{
int x,y,dis_value;
queue_element(int x_,int y_,int dis_value_):
x(x_),y(y_),dis_value(dis_value_){}
bool operator < (const queue_element &other) const
{
return dis_value>other.dis_value;
}
};
inline void dijkstra()//可以不带参数,也可以把起点带进来
{
priority_queue<element> q;//优先队列大法吼
q.push(element(1,0));//把起点压进去
while(!q.empty())//不空就说明还有点没搜完
{
element k=q.top();//取出队首
q.pop();
if(vis[k.node])//如果已经在集合中(被搜到过)
continue;//扔掉
vis[k.node]=1;//标记
dis[k.node]=k.value;//存下最短路(由于优先队列的排序已经相当于完成了松弛,所以这就是答案)
for(vector<edge>::iterator it=v[k.node].begin();it!=v[k.node].end();++it)//用指针遍历邻接表
q.push(element(it->node,it->weight+k.value));//松弛
}
}
SPFA
Permítanme hablar de aquí, a menos que exista un lado derecho negativo y un anillo negativa a utilizar SPFA, el otro no, y no lo use;
el algoritmo de Dijkstra y esta diferencia todavía es cada vez más grande:
- Cola en lugar de priority_queue;
- Cuando un punto fuera del equipo, para limpiarlo de la marca, para asegurarse de que se puede recorrer de nuevo;
- Contar el número de Traverse cada punto, si el tiempo es mayor que o igual a N, lo que indica un anillo negativa;
Aquí no es explicar la profundidad de este algoritmo:
bool SPFA()
{
queue<int> q;//队列
memset(dis,127/3,sizeof(dis));//初始化一个很大的数
dis[s]=0;//原点最短路是0
q.push(s);//原点入队
vis[s]=1;//标记入队
while(!q.empty())//队列不空说明没跑完
{
int k=q.front();//取出队首
q.pop();
vis[k]=0;//擦去标记
++cnt[k];//统计次数
if(cnt[k]>=n)//如果超过n-1说明有负环
return 0;//报错
for(vector<edge>::iterator it=v[k].begin();it!=v[k].end();++it)//邻接表遍历相连的边
if(dis[it->node]>dis[k]+it->weight)//如果可以松弛
{
dis[it->node]=dis[k]+it->weight;//松弛
if(!vis[it->node])//如果被松弛的点不在队列里
{
vis[it->node]=1;//标记入队
q.push(it->node);//入队
}
}
}
return 1;//顺利完成
}