Dijkstra+记忆化搜索
首先用Dijkstra分别找到悟空和唐僧从起到终点的最短路径
最短路径的性质d[i] + edge[i][j] == d[j] 其中j为最短路径上的点,则i也为最短路径上的点。
由这个性质我们可以从终点逆向找到所有的最短路径上的点,做一遍记忆化搜索就可以得到结果。
#include <iostream>
#include <memory.h>
#include <stdio.h>
using namespace std;
const int M = 320;
const int INF = 1 << 30;
int n,m;
int d[M][M],d1[M],d2[M],dp[M][M];
void INIT()
{
int u,v,w;
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= n;j++)
d[i][j] = INF;
}
for(int i = 0;i < m;i++)
{
scanf("%d%d%d",&u,&v,&w);
if(d[u][v] > w)
d[u][v] = d[v][u] = w;
}
memset(dp,-1,sizeof(dp));
return;
}
void Dijkstra(int s,int dist[])
{
int cover[M];
memset(cover,0,sizeof(cover));
for(int i = 1;i <= n;i++)
dist[i] = INF;
int temp,flag;
dist[s] = 0;
for(int i = 0;i < n;i++)
{
temp = INF;
for(int j = 1;j <= n;j++)
if(cover[j] == 0 && dist[j] < temp)
{
flag = j;
temp = dist[j];
}
cover[flag] = 1;
for(int j = 1;j <= n;j++)
if(cover[j] == 0 && d[flag][j] < INF && dist[j] > dist[flag] + d[flag][j])
dist[j] = dist[flag] + d[flag][j];
}
return;
}
int dfs(int a,int b)
{
if(dp[a][b] > -1)
return dp[a][b];
int i,j,v = 0;
/*if(a == b)
{
v++;
for(i = 1;i <= n;i++)
{
if(d1[i] + d[i][a] != d1[a])
continue;
for(j = 1;j <= n;j++)
if(d2[j] + d[j][b] == d2[b])
v = max(v,dfs(i,j)+1);
}
}*/
for(i = 1;i <= n;i++)
if(d1[i] + d[i][a] == d1[a])
v = max(v,dfs(i,b));
for(j = 1;j <= n;j++)
if(d2[j] + d[j][b] == d2[b])
v = max(v,dfs(a,j));
if(a==b)v++;
dp[a][b] = v;
return v;
}
int main()
{
while(cin >> n >> m && !(n == 0 && m == 0))
{
INIT();
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
dp[a][c] = 0;
if(a == c)
dp[a][c] = 1;
Dijkstra(a,d1);
Dijkstra(c,d2);
cout << dfs(b,d) << endl;
}
system("pause");
return 0;
}