题目链接: 传送门
题意很重要。。
就是求求起点到终点按要求走有多少条路径。对于任意两点A,B,能从A走到B的条件是存在一条从B到终点的路的长度 小于任意一条A到终点的路,即B到终点的最短路小于A到终点的最短路。为什么呢?想一下,现在要在B到终点的路径中找出一条路满足它的长度小于 A到终点的最短路(这个好想,体会任意那两个字),所以当B到终点的最短路满足上述条件时,才满足最开始那个条件。(因为如果B到终点的最短路都不满足小于任意一条A到终点的路的话,那么其他的就更不满足了。。)
然后就是dfs搜路径数了。。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <string> #include <cctype> #include <vector> #include <cstdio> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #define ll long long #define maxn 1010 #define pp pair<int,int> #define INF 0x3f3f3f3f #define max(x,y) ( ((x) > (y)) ? (x) : (y) ) #define min(x,y) ( ((x) > (y)) ? (y) : (x) ) using namespace std; vector < pp > eg[maxn]; int n,m,dis[maxn],dp[1010]; bool vis[1010]; void spfa() { queue <int> Q; memset(vis,0,sizeof(vis)); memset(dis,INF,sizeof(dis)); dis[2]=0;Q.push(2); while(!Q.empty()) { int u=Q.front();Q.pop(); vis[u]=0; for(int i=0;i<eg[u].size();i++) { int v=eg[u][i].first; int w=eg[u][i].second; if(dis[v]>dis[u]+w) { dis[v]=dis[u]+w; if(!vis[v]) { vis[v]=1; Q.push(v); } } } } } int dfs(int u) { if(u==2) return 1; if(dp[u]>=0) return dp[u]; dp[u]=0; for(int i=0;i<eg[u].size();i++) { int v=eg[u][i].first; if(!vis[v]&&dis[v]<dis[u]) { vis[v]=1; dp[u]+=dfs(v); vis[v]=0; } } return dp[u]; } int main() { int u,v,c; while(~scanf("%d%d",&n,&m)&&n) { for(int i=1;i<=n;i++) eg[i].clear(); while(m--) { scanf("%d%d%d",&u,&v,&c); eg[u].push_back(make_pair(v,c)); eg[v].push_back(make_pair(u,c)); } spfa(); memset(dp,-1,sizeof(dp)); memset(vis,0,sizeof(vis)); vis[1]=1; printf("%d\n",dfs(1)); } return 0; }
POJ 2662-A Walk Through the Forest(最短路+记忆化搜索)
原文地址:http://blog.csdn.net/qq_16255321/article/details/41394289