hdu 1142 A Walk Through the Forest 最短路

题目大意:对于图中节点要从起点走向终点,而且能从A节点走向B节点的条件是在B点存在一条到终点的路径,且这条路径的长度小于任何从A节点通往终点路径的长度,求共有几种走法。

对于图中限制条件,其实只要判断从B到终点的最短路径是否小于从A点到终点的最小距离,若小于,则可以,否则不可以。

经过这样转化后,题目将十分明显,深搜即可,但发现图中节点十分多,最多能达到1000个,所以深搜过程中要用记忆化搜索。

#include <stdio.h>
#include <string.h>
#define INF 2000000 
int map[1010][1010],n,m;
int low[1010],s[1010];//low存放最短路径,s为标志数组,看某节点的最短路径是否求出
int cap[1010];//记忆化搜索用到的,cap[i]记录从节点i到终点的走法数目
int dfs(int i)//记忆化搜索
{
	int j;
	if(i==2)
		return 1;
	if(cap[i]!=0)
		return cap[i];
	for(j=1;j<=n;j++)
		if(i!=j&&map[i][j]<INF&&low[j]<low[i])//限制条件
			cap[i]+=dfs(j);
	return cap[i];
}

int main()
{
	int i,j,k;
	int x,y,w;
	int ans,min,u;
	while(1)
	{
		memset(cap,0,sizeof(cap));
		memset(s,0,sizeof(s));
		scanf("%d",&n);
		if(n==0)
			break;
		scanf("%d",&m);
		for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
			{
				if(i==j)
					map[i][j]=0;
				else
					map[i][j]=INF;
			}
		for(i=1;i<=m;i++)
		{
			scanf("%d%d%d",&x,&y,&w);
			map[y][x]=map[x][y]=w;
		}
		for(i=1;i<=n;i++)//用的是dijkstra算法
            low[i]=map[2][i];
        s[2]=1;
        for(i=1;i<n;i++)
        {
            min=INF;
            for(j=2;j<=n;j++)
            {
                if(s[j]==0&&low[j]<min)
                {
                    min=low[j];
                    u=j;
                }
            }
            s[u]=1;
            for(j=1;j<=n;j++)
            {
                if(s[j]==0&&low[j]>low[u]+map[u][j]&&map[j][u]<INF)
                    low[j]=low[u]+map[u][j];
            }
		}
		ans=dfs(1);
		printf("%d
",ans);
	}
	return 0;
}


 

原文地址:https://www.cnblogs.com/vermouth/p/3710203.html