您的位置:首页 > 其它

最短路径与次短路径的条数 POJ 3463

2010-10-25 15:53 232 查看
http://poj.org/problem?id=3463

/*
题目类型;最短路-—最短路和相差一个单位的次短路的条数和
//本题关键在于理解Dijkstra的贪心思想
解题思路:
本题若开始直接在Dijkstra中加入针对加1的递推式, 必须在Dijkstra的过程中加入DFS, 很繁琐. 改换求次短路, 然后判断次短路是否比最短路长1.
解法一、A*求第K短路,把前面K条路都求出来,pku 2449 ,但是据说这个题的最后答案超过10^8,把路全部找出来肯定会爆priority_queue
解法二、
改进Dijkstra算法,。将状态扩展到二维,第一维仍然是顶点编号,第二维的长度为2,分别用于记录最短路和次短路。
这样的数据有两个,dist[][2]记录距离,cnt[][2]计数。

更新状态时:
1)新值小于最短路径长:更新最短路径长,计数;次短路径长,计数
2)新值等于最短路径长:更新最短路径计数
3)新值大于最短路径长,小于次短路径长:更新次短路径长,计数
4)新值等于次短路径长:更新次短路径计数

值得注意的是,题目图有重边,所以不能用邻接矩阵存储。
本题可以与UESTC 1053 Shortest road(只求最短路的条数,但最短路中的路径只有一条不同即可),HDU 1459(只求最短路的条数,但是不同最短路的最短路的不能包含相同的路)。本题和UESTC 1053 Shortest road最短路均可重复,只有一条不同即可

*/
#include<iostream>
#include<vector>
using namespace std;
const int inf = 0x7fffffff;
const int MAXN = 1001;//最多顶点数
const int MAXM = 10001;//最多边数
struct Edge
{
int v;
int w;
};
int n, m;//顶点数,边数
int edgenum;
int src, dest;//起点与终点
vector<Edge> adj[MAXN];

int d[MAXN][2];//d[i][0]表示从起点到i的最短距离,d[i][1]表示从起点到i的次短距离
bool visit[MAXN][2];
int cnt[MAXN][2];//cnt[i][0]表示从起点到i的最短路径的条数
int dijkstrea()
{
int i, j, k, v, min;
for(i=1; i<=n; i++)//初始化d[][],cnt[][],visit[][]
{
d[i][0] = inf;
d[i][1] = inf;
visit[i][0] = false;
visit[i][1] = false;
cnt[i][0] = inf;
cnt[i][1] = inf;
}
//对原点的初始化
d[src][0] = 0;
cnt[src][0] = 1;
//final[src][0] = true; 此处不能将final[src][0]的值赋值为true,因为本题使用邻接表实现,d[i][0],d[i][1]没有初始化为与源点的距离
for(i=1; i<2*n; i++)//此处要找最短路径与次短路径,因此要循环2*n次
{
min = inf;
v = -1;
for(j=1; j<=n; j++)
{
if(!visit[j][0] && d[j][0] < min)//找最短路径
{
min = d[j][0];
k = 0;
v = j;
}
else if(!visit[j][1] && d[j][1] < min)//找次短路径
{
min = d[j][1];
k = 1;
v = j;
}
}
if(v == -1)
break;
visit[v][k] = true;
for(j=0; j<adj[v].size(); j++)
{
int u = adj[v][j].v;
int w = adj[v][j].w;
if(d[u][0] > min + w)//新值比最短路径小,则更新最短路径,计数;次短路径,计数
{
d[u][1] = d[u][0];//更新次短路径
d[u][0] = min + w;//更新最短路径

cnt[u][1] = cnt[u][0];//更新次短路径计数
cnt[u][0] = cnt[v][k];//更新最短路径计数
}
else if(d[u][0] == min + w)//新值等于最短路径,则更新最短路径的计数
{
cnt[u][0] += cnt[v][k];
}
else if(d[u][1] > min + w)//新值小于次短路径,则更新次短路径与计数
{
d[u][1] = min + w;
cnt[u][1] = cnt[v][k];
}
else if(d[u][1] == min + w)//新值等于次短路径,则更新次短路径的计数
{
cnt[u][1] += cnt[v][k];
}
}
}
int num = cnt[dest][0];//表示最短路径的条数
if(d[dest][0] + 1 == d[dest][1])//表示次短路径与最短路径是否差一
num += cnt[dest][1];
return num;
}
int main()
{
//	freopen("in.txt","r",stdin);
int i, a, b, w, t;
Edge temp;
scanf("%d", &t);
while(t--)
{
scanf("%d %d", &n, &m);
for(i=1; i<=n; i++)
{
adj[i].clear();
}
for(i=1; i<=m; i++)
{
scanf("%d %d %d", &a, &b, &w);
temp.v = b;
temp.w = w;
adj[a].push_back(temp);
}
scanf("%d%d", &src, &dest);
printf("%d/n", dijkstrea());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: