HDU 1142 A Walk Through the Forest(Dijkstra+Dfs(第一次用记忆化搜索))

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

 

题意:这题的题意很重要,起点是1,终点是2,现在主人公已经知道,所有边的长度,然后他开始选择走不走某条边了。。

对于图中的每条边(A,B),他选这条边的前提是:存在一条B到终点的路径,比所有从A道终点的路径都短(即只要B到2的最短路径比A到2的最短路径短就存在了),选择完所有可以走的边后,问一共有多少条从1到2的路径

 

 

因为对于每条边(A,B)都要知道A到2的最短路和B到2的最短路,对于每个点都用Dijkstra的话O(n^3)超时,注意到,每次都是和2的最短路,所以灵活点,以2为起点用以次Dijkstra就可以求出所有结果。

 

然后用深搜,搜出所有的边,但是会超时,所以要用到记忆化搜索,要用辅助数组来保存结果,ans[now]表示now到终点一共有多少条路。开始初始化为0。。。。。由于某个点,可能有多条路经过,用了记忆化搜索,当不是第一次经过的时候,ans[now]已经有答案了。。。。要特别注意的是这里其实根本不需要用vis[]来标记有每走过,ans[now]已经记录了有每走过了。。。。。。。这里跟Dfs中for里vis[]区分开来。。。。。

 

记忆化搜索是为了避免重复做同一件事(这题是为了避免重复计算某点到终点的路径数)

 

而,深搜for里的vis[]是为了当从另一条路经过该点时能够经过。。

 

代码:

#include <iostream>
#include <vector>
using namespace std;

const int M = 1111;
const int INF = 1 << 30;

int d[M];
int g[M][M];
bool used[M];
//bool vis[M];
int ans[M];
int compare;
int n, m;



//vector <int> gg[1010];


void D(int star)//记录所有到2的最短路径
{
    for (int i = 1; i <= n; i++)
    {
        d[i] = INF;
    }
    memset(used, 0, sizeof(used));

    d[star] = 0;
    for (int cnt = 0; cnt < n; cnt++)
    {
        int  min = INF;
        int min_num = 0;
        for (int i = 1; i <= n; i++)
        {
            if (!used[i] && min > d[i])
            {
                min = d[i];
                min_num = i;
            }
        }

        used[min_num] = 1;

        for (int i = 1; i <= n; i++)
        {
            if (!used[i] && d[i] > d[min_num] + g[min_num][i])
            {
                d[i] = d[min_num] + g[min_num][i];
            }
        }

    }
}


int Dfs(int now)
{
    if (ans[now])
    {
        return ans[now];
    }
    if (now == 2)
    {
        return 1;
    }

    for (int i = 1; i <= n; i++)
    {
        if (/*!vis[i]  && */g[now][i] != INF && d[now] > d[i])
        {
            
            ans[now] += Dfs(i);
        }
    }
    return ans[now];
}


int main()
{
    

    while (scanf("%d", &n), n)
    {
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            g[i][j] = INF;
        }
    }

        scanf("%d", &m);
                
        while (m--)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);

            g[a][b] = g[b][a] = c;
        }

        D(2);
        memset(ans, 0, sizeof(ans));//ans[i]表示i道终点路径的条数
        //memset(vis, 0, sizeof(vis));
        //vis[1] = 1;
        printf("%d\n", Dfs(1));
    }
    return 0;
}

 

posted on 2012-08-27 14:45  [S*I]SImMon_WCG______*  阅读(253)  评论(0编辑  收藏  举报

导航