title: A Walk Through the Forest
tags: [acm,杭电,最短路径,深搜]
Problem 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
题意
要求从点1到点2路径的条数,但是题目中还有一个要求,比如:
1---->a---->b----->2
这里要求a到2的最短路径 大于b到2的最短路径,此时这条路才是可以选的。问你一共有多少条这种线路
分析
找出所有的路径用搜索,求出点到点之间的距离用最短路径算法。
对于搜索,第二组测试数据如图表示
图中红色框的部分是完全相同的搜索过程,如果不管这些重复的部分直接硬来的话就会超时(提交超时),用个标记数组,来标记每条路径是否已经搜索过,用dp[]来标记的话,图中的7这个点,经过3---> 7--->.......
经过7的路径已经搜索过了,此时dp[7]就不再为0,他的值应该为2,因为经过7有两条路径到达2点。
那么等搜到4---->7---->..... 7之后的路径就不用搜了。具体看代码
代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
int road[1051][1051];
int dis[1051];
int flag[1051];
int n,sum=0;
void Dij()
{
int vest[n+1];
for (int i=1; i<=n; i++)
{
dis[i]=road[2][i];
vest[i]=0;
}
vest[2]=1;
int op=2;
int count1=1;
while (count1<n)
{
int min1=inf;
for (int i=1; i<=n; i++)
if (vest[i]==0&&dis[i]<min1)
{
min1=dis[i];
op=i;
}
vest[op]=1;
count1++;
for (int i=1; i<=n; i++)
{
if (vest[i]==0&&dis[i]>dis[op]+road[op][i])
{
dis[i]=dis[op]+road[op][i];
}
}
}
}
int dp[1051];
int dfs(int x)
{
if (dp[x])return dp[x];//经过x点的路径一经搜索了
if (x==2)
{
return 1 ;//产生一条合法的路径
}
for (int i=1; i<=n; i++)
{
if (flag[i]==0&&road[x][i]!=inf&&dis[x]>dis[i])
{
flag[i]=1;
dp[x]+=dfs(i);
flag[i]=0;
}
}
return dp[x];
}
int main()
{
while (scanf("%d",&n),n)
{
int m;
sum=0;
scanf("%d",&m);
for (int i=0; i<=n; i++)
for (int j=0; j<=n; j++)
if (i==j)road[i][j]=0;
else road[i][j]=inf;
for (int i=0; i<m; i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
road[a][b]=road[b][a]=c;
}
Dij();
memset(flag,0,sizeof(flag));
memset(dp,0,sizeof(dp));
dfs(1);
flag[1]=1;
printf("%d
",dfs(1));
}
return 0;
}
/**
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
*/