最短回路アルゴリズムテンプレート(dijkstra+floyd+spfa)
49219 ワード
1.Floyd_Warshallアルゴリズム
参考:『チャレンジプログラミングコンテスト』およびhttps://blog.csdn.net/Floraqiu/article/details/81483420コア構想:d[i][j]=min{d[i][j],d[i][k]+d[k][j]}iからjまでの2つの経路があり、k点を通過するかk点を通過しないので、kを列挙するとすべての道の最短ルートを求めることができる.適用範囲:任意の2点の間の最短ルートを求めて、負の権力があることができて、有向図が無方向図であることができて、しかしnは必ず200以内でなければなりません
2.Dijkstraアルゴリズム
参考:アルゴリズムコンテスト入門クラシックとhttps://blog.csdn.net/Floraqiu/article/details/81484870コア構想:D(s,t)={Vs...Vi...Vj...Vt}はsからtの最短路を表し、iとjがこの経路上の2つの中間ノードである場合、D(i,j)は必ずiからjの最短路であり、このような最短路D(s,t)={Vs...Vi Vt}が存在し、iとtが最短路上で隣接する点である場合、D(s,i)={Vs...Vi}は必ずsからiの最短路である.Dijkstraアルゴリズムは,このような性質に基づいて,最短経路長をインクリメントすることにより,徐々に最短経路を生成する.適用状況:正権図上のユニットが最短、有向図無向図、単一ソース点からすべてのノードまでの最短
隣接マトリクスの実装:
優先キュー最適化版
3.SPFAアルゴリズム
核心構想:https://blog.csdn.net/qq_35644234/article/details/61614581最適化対象のノードを保存するために先進的な先頭のキューを設定し、最適化時にキューヘッダuを取り出すたびに、u点から離れるノードvをu点の現在の最短経路推定値で緩和操作し、v点の最短経路推定値が調整され、v点が現在のキューにない場合、v点をキューの最後に入れる.このようにキューからノードを取り出して緩和操作を行い、キューが空になるまで適用する:正の重みが負の重みを持つことができ、有向図が無方向図であり、単一のソース点からすべてのノードの最短路まで
コード参照:https://blog.csdn.net/Since_natural_ran/article/details/52955460
参考:『チャレンジプログラミングコンテスト』およびhttps://blog.csdn.net/Floraqiu/article/details/81483420コア構想:d[i][j]=min{d[i][j],d[i][k]+d[k][j]}iからjまでの2つの経路があり、k点を通過するかk点を通過しないので、kを列挙するとすべての道の最短ルートを求めることができる.適用範囲:任意の2点の間の最短ルートを求めて、負の権力があることができて、有向図が無方向図であることができて、しかしnは必ず200以内でなければなりません
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f
using namespace std;
int main()
{
int n, m, s, t;
while(~scanf("%d%d", &n, &m))
{
vector<vector<int> > dis(n);//vector
for(int i = 0; i < n; i++)
{
dis[i].resize(n, INF);// dis[i] , INF
dis[i][i] = 0;
}
for(int i = 0; i < m; i++)// a,b x
{
int a, b, x;
scanf("%d%d%d", &a, &b, &x);
if(dis[a][b] > x)
dis[a][b] = dis[b][a] = x;
}
scanf("%d%d", &s, &t);
for(int k = 0; k < n; k++)
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
{
if(dis[i][k] < INF && dis[k][j] < INF)
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
if(dis[s][t] != INF)//
printf("%d
", dis[s][t]);
else
printf("-1
");
}
return 0;
}
2.Dijkstraアルゴリズム
参考:アルゴリズムコンテスト入門クラシックとhttps://blog.csdn.net/Floraqiu/article/details/81484870コア構想:D(s,t)={Vs...Vi...Vj...Vt}はsからtの最短路を表し、iとjがこの経路上の2つの中間ノードである場合、D(i,j)は必ずiからjの最短路であり、このような最短路D(s,t)={Vs...Vi Vt}が存在し、iとtが最短路上で隣接する点である場合、D(s,i)={Vs...Vi}は必ずsからiの最短路である.Dijkstraアルゴリズムは,このような性質に基づいて,最短経路長をインクリメントすることにより,徐々に最短経路を生成する.適用状況:正権図上のユニットが最短、有向図無向図、単一ソース点からすべてのノードまでの最短
s
dis[s] = 0, dis[i] = INF
n
{
, dis X
X
X y, dis[y] = min{dis[y], dis[x]+w(x,y)}
}
隣接マトリクスの実装:
void dijkstra(int s)//s
{
memset(dis, INF, sizeof(dis));
memset(vis,0,sizeof(vis);
vis[s] = 1;
dis[s] = 0;
for(int i = 1; i <= n; i++)// n-1
{
int min_dis = INF;
int x;
for(int j = 1; j <= n; j++)// x
{
if(!vis[j] && min_dis > dis[j])
{
x = j;
min_dis = dis[j];
}
}
vis[x] = 1;// X
for(int j = 1; j <= n; j++)//
{
if(!vis[j])
dis[j] = min(dis[j], dis[x] + mapp[x][j]);//x j +dis[x]
}
}
}
優先キュー最適化版
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 105;
int dis[maxn], pre[maxn];
struct Edge//
{
int u, v, w;
Edge() {};
Edge(int uu, int vv, int ww): u(uu), v(vv), w(ww) {};
};
vector<Edge> edges;//
vector<int> G[maxn];//
void init(int nn)//
{
for(int i = 0; i <= nn; i++)
G[i].clear();
edges.clear();
}
void AddEdge(int uu, int vv, int ww)//
{
edges.push_back(Edge(uu, vv, ww));
int edgenum = edges.size();
G[uu].push_back(edgenum - 1);
}
struct node// ,dis
{
int u, d;
node() {};
node(int uu, int dd): u(uu), d(dd) {};
friend bool operator < (node a, node b)
{
return a.d > b.d;
}
};
void dijkstra(int s)
{
priority_queue<node> q;
memset(dis, INF, sizeof(dis));//dis INF
dis[s] = 0;
q.push(node(s, dis[s]));
while(!q.empty())
{
node cur = q.top();
q.pop();
int from = cur.u;
if(cur.d != dis[from])// vis ,
continue;
for(int i = 0; i < G[from].size(); i++)// dis
{
Edge e = edges[G[from][i]];
if(dis[e.v] > dis[e.u] + e.w)
{
dis[e.v] = dis[e.u] + e.w;
pre[e.v] = from;//
q.push(node(e.v, dis[e.v]));// dis
}
}
}
}
int main()
{
int n, m;
while(~scanf("%d%d", &n, &m) && n && m)
{
init(n);
for(int i = 0; i < m; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
AddEdge(u, v, w);
AddEdge(v, u, w);
}
dijkstra(1);
printf("%d
", dis[n]);
}
return 0;
}
3.SPFAアルゴリズム
核心構想:https://blog.csdn.net/qq_35644234/article/details/61614581最適化対象のノードを保存するために先進的な先頭のキューを設定し、最適化時にキューヘッダuを取り出すたびに、u点から離れるノードvをu点の現在の最短経路推定値で緩和操作し、v点の最短経路推定値が調整され、v点が現在のキューにない場合、v点をキューの最後に入れる.このようにキューからノードを取り出して緩和操作を行い、キューが空になるまで適用する:正の重みが負の重みを持つことができ、有向図が無方向図であり、単一のソース点からすべてのノードの最短路まで
コード参照:https://blog.csdn.net/Since_natural_ran/article/details/52955460
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
using namespace std;
int dis[105],visit[105];
int n,m;
class Node
{
public:
int e,v;
Node(int a,int b){e = a,v = b;}
};
vector<Node>s[105];
void spfa()
{
memset(dis,inf,sizeof(dis));
memset(visit,0,sizeof(visit));
dis[1] = 0;
queue<int>q;
q.push(1);
visit[1] = true;
while(!q.empty()){
int u = q.front();
q.pop();
visit[u] = false;
int num = s[u].size();
for(int i = 0;i < num; i++){
if(dis[u] + s[u][i].v > dis[s[u][i].e])
continue;
dis[s[u][i].e] = dis[u] + s[u][i].v;
if(!visit[s[u][i].e]){
q.push(s[u][i].e);
visit[s[u][i].e] = true;
}
}
}
}
int main()
{
// freopen("in.txt","r",stdin);
while(cin>>n>>m){
if(n == 0 && m == 0)
break;
for(int i = 1;i <= n; i++)
s[i].clear();
int a,b,c;
for(int i = 1;i <= m; i++){
cin>>a>>b>>c;
s[a].push_back(Node(b,c));
s[b].push_back(Node(a,c));//
}
spfa();
cout<<dis[n]<<endl;
}
return 0;
}