Description
Jimmy experiences a lot of stress at work these days, especially since his accident made working difficult. To relax after a hard day, he likes to walk home. To make things even nicer, his office is on one side of a forest, and his house is on the other. A nice walk through the forest, seeing the birds and chipmunks is quite enjoyable.
The forest is beautiful, and Jimmy wants to take a different route everyday. He also wants to get home before dark, so he always takes a path to make progress towards his house. He considers taking a path from A to B to be progress if there exists a route from B to his home that is shorter than any possible route from A. Calculate how many different routes through the forest Jimmy might take.
Input
Input contains several test cases followed by a line containing 0. Jimmy has numbered each intersection or joining of paths starting with 1. His office is numbered 1, and his house is numbered 2. The first line of each test case gives the number of intersections N, 1 < N <= 1000, and the number of paths M. The following M lines each contain a pair of intersections a b and an integer distance 1 <= d <= 1000000 indicating a path of length d between intersection a and a different intersection b. Jimmy may walk a path any direction he chooses. There is at most one path between any pair of intersections.
Output
For each test case, output a single integer indicating the number of different routes through the forest. You may assume that this number does not exceed 2147483647.
Sample Input
5 6
1 3 2
1 4 2
3 4 3
1 5 12
4 2 34
5 2 24
7 8
1 3 1
1 4 1
3 7 1
7 4 1
7 5 1
6 7 1
5 2 1
6 2 1
0
Sample Output
2
4
Source
Waterloo local 2005.09.24
http://acm.pku.edu.cn/JudgeOnline/problem?id=2662
http://acm.hust.edu.cn/judge/showproblem.jsp?id=10010
My code
#define MAX 1000 //问题规模,最好不超过2500
#include<stdio.h>
#include<memory.h>
long d[MAX][MAX]; //定义为全局或动态可解决栈溢出
int main()
{
int N,i,a,b,k,mini,maxi;
long M,P[MAX],T[MAX],j,mindis,maxdis,P2[MAX];
while(EOF!=scanf("%d",&N))
{
if(0==N)break; //测试样例终止条件
memset((void *)d,0,MAX*N*sizeof(long)); //最快的数组清零方式
scanf("%ld",&M);
for(j=0;j<M;j++)
{ //填充邻接矩阵d
scanf("%d%d",&a,&b);
a--;b--; //加快下面两句的速度
scanf("%ld",&d[a][b]);
d[b][a]=d[a][b]; //无向图邻接矩阵是对称的
}
//Dijkstra算法求到各节点到家的最短距离
memset((void *)P,0,N*sizeof(long)); //P存放到家的最短距离
memset((void *)T,0,N*sizeof(long)); //T存放P的上限
k=1; //k表示刚获得P标号的结点,初始为P[1]
// P[1]=0; //家到家的距离当然为0了,由于前面执行了memset,此句多余
while(k) //以k=0时(出发点)作为终止条件
{
mini=-1;
mindis=1000000;
for(i=0;i<N;i++)
{ //i=1时P[i]为0不意味着没有P标号,但i取其它值时意味着没有P标号
if(P[i]||d[k][i]==0||i==1)continue;
if(T[i]==0||T[i]>d[k][i]+P[k])T[i]=d[k][i]+P[k];
}
for(i=0;i<N;i++)
{
if(T[i]&&T[i]<mindis)
{
mindis=T[i];
mini=i;
}
}
if(-1==mini)break; //T为空意味着起点到终点无路可走
P[mini]=T[mini];
T[mini]=0;
k=mini;
}//Dijkstra完,现在P中存放到家的最短距离,为0表示距离太远
if(0==P[0])
{ //要是搞了半天无路可走,就换一组数据了
printf("0/n");
continue;
}
//下面是求number of different routes,为省空间,借用T,k
memset((void *)T,0,N*sizeof(long)); //T[i]存放起点到i点的路径数下限
memset((void *)P2,0,N*sizeof(long)); //P2[i]存放起点到i点的路径数
k=0; //k=0表示从起点开始搜索,算法类似Dijkstra算法
P2[k]=1; //显然,起点到起点有1条路
while(k!=1) //以搜索到终点作为终止条件
{
maxi=-1;
maxdis=-1;
for(i=0;i<N;i++)
{ //需要满足shorter than any possible route from A
if(P[i]>=P[k]||P[i]==0&&i!=1||d[k][i]==0)continue;
T[i]+=P2[k];
}
for(i=0;i<N;i++)
{
if(T[i]&&P[i]>maxdis)
{
maxdis=P[i];
maxi=i;
}
}
P2[maxi]=T[maxi]; //不用担心T空
T[maxi]=0;
k=maxi;
}
printf("%ld/n",P2[1]);
}
return 0;
}