最短路相关模板
2017-08-26 18:37
330 查看
spfa:
//适合稀疏图 const int N = 1010, INF = 0x3f3f3f3f; //N是点数 struct edge { int to, cost, next; }g[N*N*2]; int cnt, head ; int dis ; bool vis ; void init() //初始化 { cnt = 0; memset(head, -1, sizeof head); } void add_edge(int v, int u, int cost) //加单向边,双向边则调换v,u位置再加一次 { g[cnt].to = u, g[cnt].cost = cost, g[cnt].next = head[v], head[v] = cnt++; } void spfa(int s) //从s到其他点的最短路 { queue<int> que; memset(vis, 0, sizeof vis); memset(dis, 0x3f, sizeof dis); que.push(s), dis[s] = 0, vis[s] = true; while(! que.empty()) { int v = que.front(); que.pop(); vis[v] = false; for(int i = head[v]; i != -1; i = g[i].next) { int u = g[i].to; if(dis[u] > dis[v] + g[i].cost) { dis[u] = dis[v] + g[i].cost; if(! vis[u]) que.push(u), vis[u] = true; } } } }
spfa判负环:
//用spfa判断有没有点入队超过n次,若有则存在负环,用等于n次判断是不对的,比如只有一个点 bool spfa(int s, int n) { queue<int> que; memset(dis, 0x3f, sizeof dis); memset(num, 0, sizeof num); memset(vis, 0, sizeof vis); que.push(s), dis[s] = 0, vis[s] = true, num[s]++; while(! que.empty()) { int v = que.front(); que.pop(); vis[v] = false; for(int i = head[v]; i != -1; i = g[i].next) { int u = g[i].to; if(dis[u] > dis[v] + g[i].cost) { dis[u] = dis[v] + g[i].cost; if(! vis[u]) { que.push(u), vis[u] = true, num[u]++; if(num[u] > n) return true;//入队次数超过点数,存在负环 } } } } return false; }
二叉堆优化djikstra:
//适合稠密图 typedef pair<int,int> pii; const int N = 1010, INF = 0x3f3f3f3f; //N是点数 struct edge { int to, cost, next; }g[N*N*2]; int cnt, head ; int dis ; void init() //初始化 { cnt = 0; memset(head, -1, sizeof head); } void add_edge(int v, int u, int cost) //加边 { g[cnt].to = u, g[cnt].cost = cost, g[cnt].next = head[v], head[v] = cnt++; } void dijkstra(int s) //从s到其他点的最短路 { priority_queue<pii, vector<pii>, greater<pii> > que; memset(dis, 0x3f, sizeof dis); dis[s] = 0; que.push(pii(dis[s], s)); while(! que.empty()) { pii p = que.top(); que.pop(); int v = p.second; if(dis[v] < p.first) continue; for(int i = head[v]; i != -1; i = g[i].next) { int u = g[i].to; if(dis[u] > dis[v] + g[i].cost) { dis[u] = dis[v] + g[i].cost; que.push(pii(dis[u], u)); } } } }
floyd:
//点下标1~n const int N = 100 + 10, INF = 0x3f3f3f3f; int dis[N][N]; //dis[v][u]初始为(v,u)的边权值,存在设为INF,但dis[i][i]=0 void floyd(int n) { for(int k = 1; k <= n; k++) for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]); }
floyd求无向图最小环:
关于记录路径:定义pro[i][j]为点i到点j路径上的倒数第二个点,倒数第一个自然是j,初始化pro[i][j]为i。当dis[i][j] > dis[i][k] + dis[k][j]成立时,意味着点i到点j的路径要改成点i到点k再到点j,而dis[k][j]已知,意味着pro[k][j]已知,即点k到点j的路径已知,所以此时应该把pro[k][j]存到pro[i][j]中,即pro[i][j] = pro[k][j]//点下标1~n const int N = 110, INF = 1<<28; int tot; int g , dis , pro , path ; int floyd(int n) { int res = INF; for(int k = 1; k <= n; k++) { for(int i = 1; i < k; i++) for(int j = i+1; j < k; j++) { int tmp = dis[i][j] + g[i][k] + g[k][j]; //这里INF要保证3*INF不溢出 if(res > tmp) { res = tmp; tot = 0; int p = j; while(p != i) { path[tot++] = p; p = pro[i][p]; } path[tot++] = i, path[tot++] = k; } } for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(dis[i][j] > dis[i][k] + dis[k][j]) { dis[i][j] = dis[i][k] + dis[k][j]; pro[i][j] = pro[k][j]; } } return res; } int main() { int n, m; while(~scanf("%d%d", &n, &m)) { for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) { if(i == j) g[i][j] = dis[i][j] = 0; else g[i][j] = dis[i][j] = INF; pro[i][j] = i; } for(int i = 1; i <= m; i++) { int v, u, c; scanf("%d%d%d", &v, &u, &c); g[v][u] = g[u][v] = dis[v][u] = dis[u][v] = min(g[v][u], c); } int res = floyd(n); if(res == INF) printf("No solution.\n"); else { for(int i = tot-1; i >= 0; i--) printf("%d%c", path[i], i == 0 ? '\n' : ' '); } } return 0; }
k短路:
//用dijkstra+Astar求第k短路,同一条边可以经过多次 //代码是有向图,有向图可能第k短路可能不存在,且要建正向图和反向图 //无向图第k短路一定存在,且只需要建一个无向图即可 typedef pair<int, int> pii; const int N = 1000 + 10, INF = 0x3f3f3f3f; struct edge { int to, cost, next; }g[N*200]; struct node { int h, g, v;//f,g是估价函数中相应的值 friend bool operator< (node a, node b) { return a.h + a.g > b.h + b.g; } }; int cnt, head , rhead ; int dis , num ; bool vis ; void init() { cnt = 0; memset(head, -1, sizeof head); memset(rhead, -1, sizeof rhead); } void add_edge(int v, int u, int cost) { g[cnt].to = u, g[cnt].cost = cost, g[cnt].next = head[v], head[v] = cnt++; } void radd_edge(int v, int u, int cost) { g[cnt].to = u, g[cnt].cost = cost, g[cnt].next = rhead[v], rhead[v] = cnt++; } void dijkstra(int s, int t) { priority_queue<pii, vector<pii>, greater<pii> > que; memset(dis, 0x3f, sizeof dis); memset(vis, 0, sizeof vis); que.push(pii(0, s)), dis[s] = 0; while(! que.empty()) { int v = que.top().second; que.pop(); if(vis[v] == true) continue; vis[v] = true; for(int i = rhead[v]; i != -1; i = g[i].next) { int u = g[i].to; if(dis[u] > dis[v] + g[i].cost) { dis[u] = dis[v] + g[i].cost; que.push(pii(dis[u], u)); } } } } int a_star(int s, int t, int k) { if(s == t) k++; if(dis[s] == INF) return -1; priority_queue<node> que; memset(num, 0, sizeof num); node e; e.v = s, e.g = 0, e.h = dis[s]; que.push(e); while(! que.empty()) { node p = que.top(); que.pop(); num[p.v]++; if(num[p.v] > k) continue;//一个优化 if(num[t] == k) return p.g; for(int i = head[p.v]; i != -1; i = g[i].next) { e.v = g[i].to, e.g = p.g + g[i].cost, e.h = dis[e.v]; que.push(e); } } return -1; } int main() { int n, m; while(~ scanf("%d%d", &n, &m)) { init(); int a, b, c; for(int i = 1; i <= m; i++) { scanf("%d%d%d", &a, &b, &c); add_edge(a, b, c); radd_edge(b, a, c); } int s, t, k; scanf("%d%d%d", &s, &t, &k);//求从s到t的最短路 dijkstra(t, s); //求出从终点t到所有点的最短路 int ans = a_star(s, t, k); printf("%d\n", ans); } return 0; }
次短路:
//点下标1~n,求从1到n的次短路,一条边可以走多次 typedef pair<int, int> P; typedef long long ll; const int N = 5010; struct edge { int to, cost, next; }g[N*100]; int cnt, head ; int dis1 , dis2 ; bool vis ; void add_edge(int v, int u, int cost) { g[cnt].to = u, g[cnt].cost = cost, g[cnt].next = head[v], head[v] = cnt++; } void dijkstra(int s) { memset(dis1, 0x3f, sizeof dis1); memset(dis2, 0x3f, sizeof dis2); priority_queue<P, vector<P>, greater<P> > que; dis1[s] = 0; que.push(P(dis1[s], s)); while(! que.empty()) { P p = que.top(); que.pop(); int v = p.second; if(dis2[p.second] < p.first) continue; for(int i = head[v]; i != -1; i = g[i].next) { int u = g[i].to, d = p.first + g[i].cost; if(dis1[u] > d) { swap(dis1[u], d); que.push(P(dis1[u], u)); } if(dis2[u] > d && dis1[u] < d) {//当前条件限制的次短路严格小于最短路,若允许次短路等于最短路,改dis1[u]<=d dis2[u] = d; que.push(P(dis2[u], u)); } } } } int main() { int n, m, a, b, c; while(~ scanf("%d%d", &n, &m)) { cnt = 0; memset(head, -1, sizeof head); for(int i = 1; i <= m; i++) { scanf("%d%d%d", &a, &b, &c); add_edge(a, b, c), add_edge(b, a, c); } dijkstra(1); printf("%d\n", dis2 ); } return 0; }
//另外一个次短路模板 typedef pair<int, int> P; typedef long long ll; const int N = 5010, INF = 0x3f3f3f3f; struct edge { int to, cost, next; }g[N*100]; int cnt, head ; int dis1 , dis2 ; bool vis ; void add_edge(int v, int u, int cost) { g[cnt].to = u, g[cnt].cost = cost, g[cnt].next = head[v], head[v] = cnt++; } void spfa(int s, int dis[]) { memset(vis, 0, sizeof vis); queue<int> que; que.push(s), dis[s] = 0, vis[s] = true; while(! que.empty()) { int v = que.front(); que.pop(); vis[v] = false; for(int i = head[v]; i != -1; i = g[i].next) { int u = g[i].to; if(dis[u] > dis[v] + g[i].cost) { dis[u] = dis[v] + g[i].cost; if(! vis[u]) que.push(u), vis[u] = true; } } } } int main() { int n, m, a, b, c; while(~ scanf("%d%d", &n, &m)) { cnt = 0; memset(head, -1, sizeof head); for(int i = 1; i <= m; i++) { scanf("%d%d%d", &a, &b, &c); add_edge(a, b, c), add_edge(b, a, c); } memset(dis1, 0x3f, sizeof dis1); memset(dis2, 0x3f, sizeof dis2); spfa(1, dis1); spfa(n, dis2); int res = INF; for(int i = 1; i <= n; i++) for(int j = head[i]; j != -1; j = g[j].next) { int u = g[j].to; int tmp = dis1[i] + dis2[u] + g[j].cost; if(tmp > dis1 && tmp < res) res = tmp;//tmp >= dis1 } printf("%d\n", res); } return 0; }
相关文章推荐
- 最短路相关模板、总结
- HDU 2544 最短路——简单的模板题 dijkstra
- floyd 最短路 模板
- 后缀数组 相关问题模板
- POJ 1874 畅通工程续(最短路模板题)
- poj 2449 k短路--模板
- poj 2449 k短路模板(有环)
- Nginx基础入门之相关配置模板样例参考
- 最短路(HDU-2544)(迪杰斯特拉模板)
- 【模板】【最短路】【Dijkstra+Heap,SPFA】
- poj2449 K短路模板题
- 最短路 Dijkstra模板
- hdu2544 最短路,dijstra(模板)
- 基于空间相关的图像模板匹配及MATLAB实现
- K短路问题模板(spfa+A*)
- 【模板】最短路
- hdu2680 Choose the best route(spfa求最短路模板题)
- A*求单元第k短路的模板
- 高斯消元中用到的相关概念和模板
- HDU-2544-最短路-模板