题意:起点是1,终点是2,只能从离终点远的点走到离终点近的点,问从起点到终点一共有多少种走法。
分析:利用spfa求得以2为起点所有点的距离,然后利用记忆化搜索求得路径的个数。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int oo=1e9;
const int mm=5000;
const int mn=510000;
int ver[mn],cost[mn],next[mn],q[mn];
int head[mm],dis[mm],vis[mm],num[mm];
int n,m,src,edge;
void addedge(int u,int v,int c)
{
ver[edge]=v,cost[edge]=c,next[edge]=head[u],head[u]=edge++;
ver[edge]=u,cost[edge]=c,next[edge]=head[v],head[v]=edge++;
}
bool spfa()
{
int i,u,v,l,r=0,tmp;
for(i=0;i<=n;i++) dis[i]=oo;
dis[q[r++]=src]=0;
for(l=0;l<r;(++l>mn)?l=0:l)
for(i=head[u=q[l]],vis[u]=0;i>=0;i=next[i])//错了好多遍,到最后才发现居然只写了vis[u],而没写等于0,无语。。
if(dis[v=ver[i]]>(tmp=dis[u]+cost[i]))
{
dis[v]=tmp;
if(vis[v]) continue;
vis[q[r++]=v]=1;
if(r>=mn) r=0;
}
return 1;
}
int dfs(int x)
{
if(num[x]>0) return num[x];
if(x==2) return 1;
for(int i=head[x];i!=-1;i=next[i])
{
int v=ver[i];
if(dis[x]>dis[v])
{
num[x]+=dfs(v);
}
}
return num[x];
}
int main()
{
int u,v,c,i;
while(scanf("%d",&n)!=EOF)
{
if(n==0) break;
scanf("%d",&m);
for(edge=i=0;i<=n;i++) head[i]=-1,vis[i]=0;
src=2;
while(m--)
{
scanf("%d%d%d",&u,&v,&c);
addedge(u,v,c);
}
spfa();
memset(num,0,sizeof(num));
printf("%d\n",dfs(1));
}
return 0;
}