https://vjudge.net/problem/UVA-10917
给出N点M边的无向图,没重边。对于点A,B,当且仅当从B到终点的最短路小于任何一条从A到终点的最短路时,才考虑从A走到B,否则不会走A-B。一开始理解错了题意以为是走最短路的不同方案。
令f(x)表示从x到2的不同方案,则 f[2]=1, f[x]=SUM{ f[i] | connect[x][i]&&dis[i]<dis[x] } dis[x]表示x-2的最短路长度。记忆化搜索就好了。
换言之要想要走A-B这条路必须满足的条件就是dis[B]<dis[A],只要看透这一点就容易多了!!!
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 #define inf 0x3f3f3f3f 8 const int maxn=1005; 9 vector<int>g[maxn]; 10 int e[1005][1005],dis[1005],f[1005]; 11 void dij(int N) 12 { 13 bool vis[1005]; 14 memset(vis,0,sizeof(vis)); 15 memset(dis,inf,sizeof(dis)); 16 dis[2]=0; 17 for(int i=1;i<=N;++i) 18 { 19 int w=inf,u=-1; 20 for(int j=1;j<=N;++j) 21 if(vis[j]==0&&dis[j]<w) { w=dis[j]; u=j;} 22 vis[u]=1; 23 for(int j=1;j<=N;++j) 24 if(!vis[j]&&e[u][j]!=inf&&dis[j]>dis[u]+e[u][j]) 25 dis[j]=dis[u]+e[u][j]; 26 } 27 } 28 int dfs(int x) 29 { 30 if(f[x]!=-1) return f[x]; 31 int s=0; 32 for(int i=0;i<g[x].size();++i) 33 { 34 int u=g[x][i]; 35 if(dis[u]<dis[x]) s+=dfs(u); 36 } 37 return f[x]=s; 38 } 39 int main() 40 { 41 int N,M,i,j,k; 42 while(cin>>N&&N){cin>>M; 43 int u,v,w; 44 memset(e,inf,sizeof(e)); 45 memset(f,-1,sizeof(f)); 46 for(i=1;i<=N;++i) e[i][i]=0; 47 for(i=1;i<=M;++i) 48 { 49 scanf("%d%d%d",&u,&v,&w); 50 g[u].push_back(v); 51 g[v].push_back(u); 52 e[u][v]=e[v][u]=w; 53 } 54 dij(N);f[2]=1; 55 printf("%d ",dfs(1)); 56 for(i=1;i<=N;++i) 57 g[i].clear(); 58 } 59 return 0; 60 } 61 /* 62 5 6 63 1 3 2 64 1 4 2 65 3 4 3 66 1 5 12 67 4 2 34 68 5 2 24 69 70 71 7 8 72 1 3 1 73 1 4 1 74 3 7 1 75 7 4 1 76 7 5 1 77 6 7 1 78 5 2 1 79 6 2 1 80 81 82 2 83 4 84 85 */