最短路模板

(1)无负权边单源最短路 堆优化dijkstra

#include<cstdio>
#include<vector>
#include<queue>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;

const int MAXN = 11234;
struct node
{
	int u, w;
	node(int u = 0, int w = 0) : u(u), w(w) {};
	bool operator < (const node& rhs) const
	{
		return w > rhs.w; //注意这里是大于,因为要小跟堆 
	}	
}; 
vector<node> g[MAXN];
int d[MAXN], n, m;

int work()
{
	priority_queue<node> q;
	REP(i, 1, n + 1) d[i] = (i == 1 ? 0 : 1e9); //注意这里i等于1的时候为0 
	q.push(node(1, 0)); //加入一开始的边 
	
	while(!q.empty())
	{
		node x = q.top(); q.pop();
		int u = x.u;
		if(d[u] != x.w) continue;  
		
		REP(i, 0, g[u].size())
		{
			int v = g[u][i].u, w = g[u][i].w;
			if(d[v] > d[u] + w)
			{
				d[v] = d[u] + w;
				q.push(node(v, d[v]));
			}
		}
	}
	return d[n];
}

int main()
{
	scanf("%d%d", &n, &m);
	while(m--)
	{
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		g[u].push_back(node(v, w));
		g[v].push_back(node(u, w));
	}
	printf("%d\n", work());
	return 0;
}

 

(2)任意两点间最短路 Floyd

//初始化 
REP(i, 0, n)
	REP(j, 0, n)
		d[i][j] = (i == j ? 0 : 1e9);
//Floyd
REP(k, 0, n)
  REP(i, 0, n)
	REP(j, 0, n)
	  if(d[i][k] != 1e9 && d[k][j] != 1e9)
	    d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
		// d[i][j] |= (d[i][k] && d[k][j]) 判断联通 

 

(3)可有负权变单源最短路SPFA(可以用来判断负环)

#include<cstdio>
#include<vector>
#include<queue>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;

const int MAXN = 11234;
struct node
{
	int v, w;
	node(int v = 0, int w = 0) : v(v), w(w) {}
};
vector<node> g[MAXN];
int d[MAXN], vis[MAXN], cnt[MAXN], n, m;

int work()
{
	queue<int> q;
	REP(i, 1, n + 1) d[i] = (i == 1 ? 0 : 1e9);
	vis[1] = 1;
	q.push(1);
	
	while(!q.empty())
	{
		int u = q.front();
		q.pop(); vis[u] = 0;
		REP(i, 0, g[u].size())
		{
			int v = g[u][i].v, w = g[u][i].w;
			if(d[v] > d[u] + w)
			{
				d[v] = d[u] + w;
				if(!vis[v])
				{
					vis[v] = 1;
					q.push(v);
					if(++cnt[v] > n) return -1;//关键!可以判断负环 
				}
			}
		}
	}
	
	return d[n];
}

int main()
{
	scanf("%d%d", &n, &m);
	while(m--)
	{
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		g[u].push_back(node(v, w));
		g[v].push_back(node(u, w));
	}
	printf("%d\n", work());
	return 0;	
} 

 

其实spfa和dijkstra非常像, dijkstra是每次找一个最近的点入队, 然后去松弛。而spfa是一个点可以入很多次, 每次都去松弛。

 

posted @ 2018-05-24 16:57  Sugewud  阅读(108)  评论(0编辑  收藏  举报