UVa10917 A Walk Through the Forest(SPFA+记忆化搜索)
题目给一张有向图,问从起点1到终点2沿着合法的路走有种走法,合法的路指从u到v的路,v到终点的距离严格小于u到终点的距离。
先SPFA预处理出所有合法的路,然后这些路肯定形成一个DAG,然后DP一下就OK了,d[u]表示u到终点2的方案数。
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 #define INF (1LL<<60) 6 #define MAXN 1111 7 #define MAXM 1111*1111 8 9 struct Edge{ 10 int u,v,w,next; 11 }edge[MAXM]; 12 int NE,head[MAXN]; 13 void addEdge(int u,int v,int w){ 14 edge[NE].u=u; edge[NE].v=v; edge[NE].w=w; 15 edge[NE].next=head[u]; head[u]=NE++; 16 } 17 18 int n; 19 long long dist[MAXN]; 20 void SPFA(){ 21 for(int i=1; i<=n; ++i) dist[i]=INF; 22 dist[2]=0; 23 bool vis[MAXN]={0}; 24 vis[2]=1; 25 queue<int> que; 26 que.push(2); 27 while(!que.empty()){ 28 int u=que.front(); que.pop(); 29 for(int i=head[u]; i!=-1; i=edge[i].next){ 30 int v=edge[i].v; 31 if(dist[v]>dist[u]+edge[i].w){ 32 dist[v]=dist[u]+edge[i].w; 33 if(!vis[v]){ 34 vis[v]=1; 35 que.push(v); 36 } 37 } 38 } 39 vis[u]=0; 40 } 41 } 42 43 int d[MAXN]; 44 int dfs(int u){ 45 if(u==2) return 1; 46 if(d[u]!=-1) return d[u]; 47 int res=0; 48 for(int i=head[u]; i!=-1; i=edge[i].next){ 49 int v=edge[i].v; 50 res+=dfs(v); 51 } 52 return d[u]=res; 53 } 54 int main(){ 55 int m,a,b,c; 56 while(~scanf("%d",&n) && n){ 57 scanf("%d",&m); 58 NE=0; 59 memset(head,-1,sizeof(head)); 60 while(m--){ 61 scanf("%d%d%d",&a,&b,&c); 62 addEdge(a,b,c); addEdge(b,a,c); 63 } 64 SPFA(); 65 int tmp=NE; NE=0; 66 memset(head,-1,sizeof(head)); 67 for(int i=0; i<tmp; ++i){ 68 int u=edge[i].u,v=edge[i].v; 69 if(dist[u]>dist[v]) addEdge(u,v,0); 70 } 71 memset(d,-1,sizeof(d)); 72 printf("%d\n",dfs(1)); 73 } 74 return 0; 75 }