题目分析:刚开始的时候确实将题目的含义理解成了求从1到2的最短路的条数,当然,就这个也没写出来(事后发现其实很容易的)。之后查看题解,才知道原来是以2为最短路原点,设1为A点,其它点为B点,则当A点到2的距离大于B点到2的距离的时候,就可以走这条路,即累计结果+1;
算法分析:只要由dijkstra算法求出源点2到各点的距离,然后用记忆化搜索求出满足条件的情况。
代码:
#include <cstdio>
#include <cstring>
const int INF = 10000000;
int g[1010][1010];
int s[1010];
int dist[1010];
int used[1010];
void dijkstra(int n)
{
int minn,vj;
memset(s,0,sizeof(s));
for (int i=1;i<=n;i++)
dist[i]=g[2][i];
s[2]=1;
for (int k=1;k<n;k++)
{
minn=INF;
vj=-1;
for (int j=1;j<=n;j++)
if (dist[j]<minn && s[j]==0)
{
minn=dist[j];
vj=j;
}
if (vj==-1) return;
s[vj]=1;
for (int i=1;i<=n;i++)
if (s[i]==0 && minn+g[vj][i]<dist[i])
{
dist[i]=minn+g[vj][i];
}
}
}
int dfs(int a,int n)
{
if (used[a]) return used[a];
if (a==2) return 1;
int sum=0;
for (int i=1;i<=n;i++)
if (g[a][i]<INF && dist[a]>dist[i])
{
if (used[a]) sum+=used[a];
else
sum+=dfs(i,n);
}
used[a]=sum;
return used[a];
}
int main()
{
int n,m;
int a,b,c;
//freopen("1.txt","r",stdin);
while (scanf("%d",&n)==1 && n!=0)
{
scanf("%d",&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
if (i!=j) g[i][j]=INF;
else g[i][j]=0;
}
for (int i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
g[a][b]=g[b][a]=c;
}
memset(used,0,sizeof(used));
dijkstra(n);
// for (int i=1;i<=n;i++)
// printf("%d ",dist[i]);
// printf("\n");
printf("%d\n",dfs(1,n));
}
return 0;
}