HDU 1142 A Walk Through the Forest(dijkstra+记忆化搜索)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1142

注意:这道题并不是求最短路的条数,而是求满足条件的条数(只要满足了条件,尽管到达家的路径不是最短的,但依然算是一条可行的路径),即找出所有满足一条路径的任意一条边A->B,A到终点的距离大于B到终点的距离的路径。

我们现在已经清楚了题目的要求,现在我们的问题是怎么用代码实现,首先,我们应该所有点到终点的最短路,即以2为起点用dijkstra对每个点松弛,然后我们再用记忆化搜索找出所有满足条件的路径,这样就行啦。

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define maxn 1005
int mp[maxn][maxn],n,m,vis[maxn],dis[maxn],pathnum[maxn],book[maxn],ans;
void djk(){//最普通的dijkstra,不过注意得以2为起点进行遍历
	int i,j,k;
	for(i=1;i<=n;i++)dis[i]=mp[2][i];
	for(i=0;i<n-1;i++){
		int mi=inf,u;
		for(j=1;j<=n;j++){
			if(dis[j]<mi&&!vis[j]){
				mi=dis[j];
				u=j;
			}
		}
		vis[u]=1;
		for(k=1;k<=n;k++){
			if(dis[k]>dis[u]+mp[u][k]){
				dis[k]=dis[u]+mp[u][k];
			}
		}
	}
}
int dfs(int now){//记忆化搜索
	int i,j,k;
	if(pathnum[now]>0)//若该点已经搜索过,则直接返回
	return pathnum[now];
	if(now==2)
	return 1;
	for(i=1;i<=n;i++){
		if(dis[i]<dis[now]&&mp[i][now]<inf){//满足条件且可走则路径条数累加
			pathnum[now]+=dfs(i);
		}
	}
	return pathnum[now];
}
int main(){
	int i,j,k;
	while(cin>>n&&n){
		ans=0;
		cin>>m;
		memset(vis,0,sizeof(vis));
		memset(pathnum,0,sizeof(pathnum));
		for(i=1;i<=n;i++){
			for(j=1;j<=n;j++){
				if(i==j)
				mp[i][i]=0;
				else
				mp[i][j]=inf;
			}
		}
		for(i=1;i<=m;i++){
			int x,y,z;
			cin>>x>>y>>z;
			mp[x][y]=z;
			mp[y][x]=z;
		}
		djk();
		dfs(1);
		cout<<pathnum[1]<<endl;
	}
}

猜你喜欢

转载自blog.csdn.net/k_r_forever/article/details/80555903