HDOJ 1142 A Walk Through the Forest
/*
HDOJ 1142
1代表他的office,2代表他的house
题目要求的是1到2之间的最短路径的数目。
首先就先求出2到所有点的最短路径,然后再求2到1的最短路的数目。
下面是题目描述中的一句话
He considers taking a path from A to B to be progress
if there exists a route from B to his home that is shorter than any possible route from A.
这句话说明了,为什么要求2到所有点的最短距离,而不是求1到所有点的最短距离。
求 2到1 的最短路径的数目时,需要用到DP的思想。
先找出2到1的最短路径上,和1相邻的顶点,然后再接着向前求,直到到2为止。
例如,从2到1的最短路径上,经过点3,3和1相邻。
那么可以保证3,4是符合上面那句描述中的点B的要求。
即 dist[3]<dist[1],接下来就变成求 2到3的最短路径的数目,
2到1的最短路径的数目,就是所有和1相邻的,满足上述要求的点的最短路径数目之和。
*/
#include <iostream>
using namespace std;
const int INF=1000010;
int graph[1001][1001]; //存储无向图
int dist[1001]; //存储最短路径
int dp[1001]; //搜索时用
int vexnum; //顶点数目
void Dijkstra(int v)
{
int min,u,i,j;
bool find[1001];
for(i=1;i<=vexnum;i++)
{
find[i]=false;
dist[i]=graph[v][i];
}
find[v]=true;
dist[v]=0;
for(i=2;i<=vexnum;i++)
{
min=INF;
for(j=1;j<=vexnum;j++)
{
if(!find[j] && dist[j]<min)
{
u=j;
min=dist[j];
}
}
if(min == INF) //v到各个点的最短路径都求完了
return ;
find[u]=true;
for(j=1;j<=vexnum;j++)
if(!find[j] && min+graph[u][j]<dist[j])
dist[j]=min+graph[u][j];
}
}
int dfs(int node)
{
if(dp[node] != -1)
return dp[node];
if(node == 2)
return 1;
dp[node]=0;
for(int i=1;i<=vexnum;i++)
if(graph[i][node]!=INF && dist[i]<dist[node])
dp[node] += dfs(i);
return dp[node]; //dp[node]存储的是从2到node的最短路径数目
}
int main()
{
int n,a,b,w,ans;
while(cin>>vexnum)
{
if(vexnum == 0)
break;
cin>>n;
for(int i=1;i<=vexnum;i++)
for(int j=1;j<=vexnum;j++)
graph[i][j]=INF;
memset(dp,-1,sizeof(dp));
for(i=1;i<=n;i++)
{
cin>>a>>b>>w;
graph[a][b]=graph[b][a]=w;
}
Dijkstra(2);
ans=dfs(1);
cout<<ans<<endl;
}
return 0;
}