2014-09-11 20:39:46
思路:这题有点意思~ 由于题目要求方案数,正向求最短路好像不能做。这里有个巧妙的做法:从终点开始,求一遍最短路,然后能从A走到B的条件就是d[A] > d[B],最后用记忆化搜索计数即可(直接搜果断TLE)
1 /************************************************************************* 2 > File Name: 1142.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Thu 11 Sep 2014 08:04:10 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <queue> 14 #include <iostream> 15 #include <algorithm> 16 using namespace std; 17 typedef long long ll; 18 const int INF = 1 << 29; 19 20 int n,m; 21 int first[1005],next[2000005],v[2000005],w[2000005]; 22 int d[1005],inq[1005],c[1005],vis[1005]; 23 int dp[1005]; 24 25 void Spfa(int s){ 26 memset(inq,0,sizeof(inq)); 27 memset(c,0,sizeof(c)); 28 memset(d,0x3f,sizeof(d)); 29 d[s] = 0; 30 queue<int> q; while(!q.empty()) q.pop(); 31 inq[s] = c[s] = 1; 32 q.push(s); 33 while(!q.empty()){ 34 int x = q.front(); q.pop(); 35 inq[x] = 0; 36 for(int y = first[x]; y; y = next[y]) if(d[v[y]] > d[x] + w[y]){ 37 d[v[y]] = d[x] + w[y]; 38 if(!inq[v[y]]){ 39 inq[v[y]] = 1; 40 c[v[y]]++; 41 if(c[v[y]] > n) return; 42 q.push(v[y]); 43 } 44 } 45 } 46 } 47 48 int Dfs(int p){ 49 vis[p] = 1; 50 if(dp[p] != -1) return dp[p]; 51 if(p == 2) return 1; 52 int sum = 0; 53 for(int y = first[p]; y; y = next[y]) if(!vis[v[y]] && d[p] > d[v[y]]){ 54 sum += Dfs(v[y]); 55 vis[v[y]] = 0; 56 } 57 return dp[p] = sum; 58 } 59 60 int main(){ 61 int a,b,c; 62 while(scanf("%d",&n) != EOF && n){ 63 scanf("%d",&m); 64 m <<= 1; 65 memset(first,0,sizeof(first)); 66 for(int i = 1; i <= m; ++i){ 67 scanf("%d%d%d",&a,&b,&c); 68 next[i] = first[a]; 69 first[a] = i; 70 v[i] = b; 71 ++i; 72 next[i] = first[b]; 73 first[b] = i; 74 v[i] = a; 75 w[i] = w[i - 1] = c; 76 } 77 Spfa(2); 78 memset(vis,0,sizeof(vis)); 79 memset(dp,-1,sizeof(dp)); 80 printf("%d\n",Dfs(1)); 81 } 82 return 0; 83 } 84