次短路问题
2014-08-05 09:58
85 查看
求最短路和次短路的数量(次短路严格大于最短路):
dijkstra算法,将状态扩展到二维:用d[u][0]记录节点最短路,d[u][1]记录节点次短路,cnt[u][0]记录节点最短路数量,cnt[u][1]记录节点次短路数量,vis[u][0]记录该点最短路是否确定,vis[u][1]记录该点次短路是否已经确定;
找出新的节点的最短路和次短路(即还没有确定的节点中最小的d[u][0],d[u][1]);
更新(与u相关的节点的最短路、次短路信息)
1、如果通过u得到的路径小于节点原来的最短路,则更新最短路、次短路信息;
2、如果通过u得到的路径等于节点原来的最短路,则更新最短路方法数;
3、如果通过u得到的路径小于节点原来的次短路,则更新次短路信息;
4、如果通过u得到的路径小于节点原来的次短路,则更新次短路方法数;
注意:这4 个更新顺序是不能条换的,且只要某一个成立就不在往下更新;
循环:循环次数应该为2*n-1(最短路的n-1次循环和此短路的n次循环)
poj3463次短路模板题目(每条边、每个节点只能走一次);
求此短路的长度(每条边、每个节点可以走多次):
此短路如果存在,就一定会是最短路上某一条边不走,而走了其它边再回到最短路上;
求解思路:
分别对起点和终点求一次单源最短路ds[i],dt[i],枚举所有的边(u,v),求出ds[u] + dt[v] + dist[u][v] 大于最短路 中最小的一个值,即为此段路值。
poj3255 求此短路模板题;(此题与上题不同的地方在于每条边、每个节点可以走多次;)
dijkstra算法,将状态扩展到二维:用d[u][0]记录节点最短路,d[u][1]记录节点次短路,cnt[u][0]记录节点最短路数量,cnt[u][1]记录节点次短路数量,vis[u][0]记录该点最短路是否确定,vis[u][1]记录该点次短路是否已经确定;
找出新的节点的最短路和次短路(即还没有确定的节点中最小的d[u][0],d[u][1]);
更新(与u相关的节点的最短路、次短路信息)
1、如果通过u得到的路径小于节点原来的最短路,则更新最短路、次短路信息;
2、如果通过u得到的路径等于节点原来的最短路,则更新最短路方法数;
3、如果通过u得到的路径小于节点原来的次短路,则更新次短路信息;
4、如果通过u得到的路径小于节点原来的次短路,则更新次短路方法数;
注意:这4 个更新顺序是不能条换的,且只要某一个成立就不在往下更新;
循环:循环次数应该为2*n-1(最短路的n-1次循环和此短路的n次循环)
poj3463次短路模板题目(每条边、每个节点只能走一次);
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<climits> #include<cctype> #include<iostream> #include<algorithm> #include<queue> #include<vector> #include<string> #include<set> #include<map> #include<stack> #define ll long long #define MAX 1010 #define INF 2000000000 #define eps 1e-8 using namespace std; struct Edge{ int from, to,dist; }; vector<int>G[MAX]; vector<Edge>edges; int n; void init(){ for (int i=0; i<=n; i++) G[i].clear(); edges.clear(); } void addEdge(int from, int to, int dist){ edges.push_back((Edge){from,to,dist}); int k = edges.size(); G[from].push_back(k-1); } int dijkstra(int s, int t){ int vis[MAX][2],d[MAX][2],cnt[MAX][2]; memset(vis,0,sizeof(vis)); memset(cnt,0,sizeof(cnt)); for (int i=0; i<n; i++){ d[i][0] = d[i][1] = INF; } d[s][0] = 0; cnt[s][0] = 1; for (int i=0; i<2*n-1; i++){ int minn = INF,flag,k; //得到新的最短路、此短路,并记下该点信息; for (int j=0; j<n; j++){ if (!vis[j][0] && d[j][0] < minn){ minn = d[j][0]; flag = 0; k = j; } else if (!vis[j][1] && d[j][1] < minn){ minn = d[j][1]; flag = 1; k = j; } } if (minn >= INF) break; vis[k][flag] = 1; for (int j = 0; j<G[k].size(); j++){ //更新与之相邻的节点信息(最短路,次短路) Edge e = edges[G[k][j]]; if (d[e.to][0] > minn + e.dist){ d[e.to][1] = d[e.to][0]; cnt[e.to][1] = cnt[e.to][0]; d[e.to][0] = minn + e.dist; cnt[e.to][0] = cnt[k][flag]; } else if (d[e.to][0] == minn + e.dist){ cnt[e.to][0] += cnt[k][flag]; } else if (d[e.to][1] > minn + e.dist){ d[e.to][1] = minn + e.dist; cnt[e.to][1] = cnt[k][flag]; } else if (d[e.to][1] == minn + e.dist){ cnt[e.to][1] += cnt[k][flag]; } } } if (d[t][1] == d[t][0] + 1){ cnt[t][0] += cnt[t][1]; } return cnt[t][0]; } int main(){ int T,m; scanf("%d",&T); while (T--){ init(); scanf("%d%d",&n,&m); int x,y,z; for (int i=0; i<m; i++){ scanf("%d%d%d",&x,&y,&z); x--; y--; addEdge(x,y,z); } int s,t; scanf("%d%d",&s,&t); s--; t--; printf("%d\n",dijkstra(s,t)); } return 0; }
求此短路的长度(每条边、每个节点可以走多次):
此短路如果存在,就一定会是最短路上某一条边不走,而走了其它边再回到最短路上;
求解思路:
分别对起点和终点求一次单源最短路ds[i],dt[i],枚举所有的边(u,v),求出ds[u] + dt[v] + dist[u][v] 大于最短路 中最小的一个值,即为此段路值。
poj3255 求此短路模板题;(此题与上题不同的地方在于每条边、每个节点可以走多次;)
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<climits> #include<cctype> #include<iostream> #include<algorithm> #include<queue> #include<vector> #include<map> #include<set> #include<string> #include<stack> #define ll long long #define MAX 10000 #define MAXN 1000000 #define INF 100000000 #define eps 1e-8 using namespace std; struct Edge{ int from ,to, dist; }; struct Node{ int num,w; bool operator < (const Node& rhs) const{ return rhs.w < w; } }; int first[MAX],next[MAXN]; vector<Edge>edges; int n; void init(){ memset(first,-1,sizeof(first)); memset(next,-1,sizeof(next)); edges.clear(); } void addEdge(int from, int to, int dist){ edges.push_back((Edge){from,to,dist}); int k = edges.size(); next[k-1] = first[from]; first[from] = k-1; } int d[MAX][2]; void dijkstra(int s, int t, int flag){ int vis[MAX]; priority_queue<Node>q; memset(vis,0,sizeof(vis)); for (int i=0; i<n; i++) d[i][flag] = (i == s ? 0 : INF); q.push((Node){s,0}); while (!q.empty()){ Node temp = q.top(); q.pop(); int u = temp.num; if (vis[u]) continue; vis[u] = 1; for (int i = first[u]; i != -1; i = next[i]){ Edge e = edges[i]; if (!vis[e.to]){ d[e.to][flag] = min(d[e.to][flag], d[u][flag] + e.dist); q.push((Node){e.to,d[e.to][flag]}); } } } } int main(){ int m; while (scanf("%d%d",&n,&m) != EOF){ int x,y,z; init(); for (int i=0; i<m; i++){ scanf("%d%d%d",&x,&y,&z); x--; y--; addEdge(x,y,z); addEdge(y,x,z); } dijkstra(0,n-1,0); dijkstra(n-1,0,1); int ans = INF; for (int i=0; i<edges.size(); i++){ int u = edges[i].from; int v = edges[i].to; if (d[u][0] + d[v][1] + edges[i].dist > d[n-1][0]){ ans = min(ans,d[u][0] + d[v][1] + edges[i].dist); } } printf("%d\n",ans); } }
相关文章推荐
- 调试PCB板中,结果短路了,这是一个非常纠结的问题,写下解决经验
- FLASH短路方法图示(解决U盘量产失败/U盘复位/无法识别硬件等问题)
- 第 K 最短路 问题
- 最短路+状态压缩dp(旅行商问题)hdu-4568-Hunter
- zoj2750.。。有关做短路的问题!!
- 最短路+状态压缩dp(旅行商问题)hdu-4568-Hunter
- HDOJ 4276 The Ghost Blows Light(最短路+树形DP)鬼吹灯问题
- Poj 1860 Currency Exchange + Poj 2240 Arbitrage (货币兑换问题+最短路)
- 最短路中汇率问题 POJ 1860 与 POJ 2240
- 网线连接问题--部分短路
- js实现最短路经问题
- hdu3790 最短路径问题 很好的双限制最短路
- 第k短路问题及其应用(POJ2449 Remmarguts' Date)
- HDU 2544 最短路 第一个图论问题。
- 差分约束系统的图解法; 形式很特殊的一种线性规划问题; 可以转化为求带负边最短路问题;
- POJ 2449 Remmarguts' Date【K短路问题,A*、dijkstra】
- [U]2.4.4 Bessie Come Home 简单最短路问题
- 最短路经问题
- 题目1447:最短路 {最短路径问题}
- PKU3463(Sightseeing)-最短路和次短路问题,dijkstra算法