题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1142
注意:这道题并不是求最短路的条数,而是求满足条件的条数(只要满足了条件,尽管到达家的路径不是最短的,但依然算是一条可行的路径),即找出所有满足一条路径的任意一条边A->B,A到终点的距离大于B到终点的距离的路径。
我们现在已经清楚了题目的要求,现在我们的问题是怎么用代码实现,首先,我们应该所有点到终点的最短路,即以2为起点用dijkstra对每个点松弛,然后我们再用记忆化搜索找出所有满足条件的路径,这样就行啦。
代码:
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define maxn 1005 int mp[maxn][maxn],n,m,vis[maxn],dis[maxn],pathnum[maxn],book[maxn],ans; void djk(){//最普通的dijkstra,不过注意得以2为起点进行遍历 int i,j,k; for(i=1;i<=n;i++)dis[i]=mp[2][i]; for(i=0;i<n-1;i++){ int mi=inf,u; for(j=1;j<=n;j++){ if(dis[j]<mi&&!vis[j]){ mi=dis[j]; u=j; } } vis[u]=1; for(k=1;k<=n;k++){ if(dis[k]>dis[u]+mp[u][k]){ dis[k]=dis[u]+mp[u][k]; } } } } int dfs(int now){//记忆化搜索 int i,j,k; if(pathnum[now]>0)//若该点已经搜索过,则直接返回 return pathnum[now]; if(now==2) return 1; for(i=1;i<=n;i++){ if(dis[i]<dis[now]&&mp[i][now]<inf){//满足条件且可走则路径条数累加 pathnum[now]+=dfs(i); } } return pathnum[now]; } int main(){ int i,j,k; while(cin>>n&&n){ ans=0; cin>>m; memset(vis,0,sizeof(vis)); memset(pathnum,0,sizeof(pathnum)); for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ if(i==j) mp[i][i]=0; else mp[i][j]=inf; } } for(i=1;i<=m;i++){ int x,y,z; cin>>x>>y>>z; mp[x][y]=z; mp[y][x]=z; } djk(); dfs(1); cout<<pathnum[1]<<endl; } }