最短路径Dijkstra(静态邻接表+优先队列模板)+ 记忆化搜索

 这道题的解题步骤是这样的:
(1)用Dijkstra求出每个点到house(也就是2号点)的最短距离,我是记录在数组dist[]中;
(2)我们要求的是office(1号点)到house(或2——>1)最短路径的条数;
(3)记忆化搜索部分是基于这样的事实,我们利用Dijkstra找到的从2号点到1号点的最短路径中的每个点v,dist[v]都小于dist[1]。

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

/*
最短路径模版(Dijkstra)
邻接表+优先队列
*/
/* 
1代表他的office,2代表他的house 

题目要求的是1到2之间的最短路径的数目。 
首先就先求出2到所有点的最短路径,然后再求2到1的最短路的数目。 
下面是题目描述中的一句话 
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.  
这句话说明了,为什么要求2到所有点的最短距离,而不是求1到所有点的最短距离。 

求 2到1 的最短路径的数目时,需要用到DP的思想。 
先找出2到1的最短路径上,和1相邻的顶点,然后再接着向前求,直到到2为止。 

例如,从2到1的最短路径上,经过点3,3和1相邻。 
那么可以保证3,4是符合上面那句描述中的点B的要求。 
即 dist[3]<dist[1],接下来就变成求 2到3的最短路径的数目, 
2到1的最短路径的数目,就是所有和1相邻的,满足上述要求的点的最短路径数目之和。 
*/ 

#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
#include<memory.h>

#define INF 0x3f3f3f3f

typedef struct
{
    int v;
    int next;
    int cost;
}Edge;

typedef struct node
{
    int v;
    int cost;
    friend bool operator<(node a, node b)
    {     //从小到大排序采用“>”号;如果要从大到小排序,则采用“<”号
        return a.cost> b.cost;       //从小到大排序
    } 
}node;

const long MAXN=2009;

int m,n;    //边,点
int head[MAXN],dp[MAXN],dist[MAXN];
Edge e[2000000];
bool visit[MAXN];

inline void init()
{
    int i,eid=0;
    int from,to,cost;
    memset(head,-1,sizeof(head));
    memset(visit,0,sizeof(visit));

    for(i=0;i<m;++i)
    {
        scanf("%d %d %d",&from,&to,&cost);
        
        e[eid].next=head[from];
        e[eid].v=to;
        e[eid].cost=cost;
        head[from]=eid++;
        
        //以下为无向图使用
        swap(from,to);
        e[eid].next=head[from];
        e[eid].v=to;
        e[eid].cost=cost;
        head[from]=eid++;
    }
}

int Dijkstra(int start,int end)  //分别表示起点和终点
{
    int i,j;
    init();
    priority_queue<node> q;

    node cur;
    cur.cost=0;
    cur.v=start;
    q.push(cur);
    for(i=1;i<=n;++i)
        dist[i]=INF;
    dist[start]=0;

    while(!q.empty())
    {
        cur=q.top();
        q.pop();
        if (visit[cur.v])
            continue;
        visit[cur.v]=true;

        for (j=head[cur.v];j!=-1;j=e[j].next)
        {
            if(dist[e[j].v] > cur.cost+e[j].cost)
            {
                node temp;
                temp.v=e[j].v;
                dist[e[j].v] = cur.cost+e[j].cost;
                temp.cost = dist[temp.v];
                q.push(temp);
            }
        }
    }
    return dist[end];
}
int dfs(int start)
{
    if(dp[start]!=-1)
        return dp[start];
    if(start==2)
        return 1;
    int j,temp,sum=0;
    for(j=head[start];j!=-1;j=e[j].next)
    {
        if(dist[start]>dist[e[j].v])
        {
            temp=dfs(e[j].v);
            sum+=temp;
        }
        dp[start]=sum;   //dp[start]存储的是从2到start的最短路径数目  
    }
    return sum;
}
int main(void)
{
    while(scanf("%d",&n)!=EOF)
    {
        if(!n)
            break;
        scanf("%d",&m);
        Dijkstra(2,1);
        memset(dp,-1,sizeof(dp));
        dfs(1);
        printf("%d\n",dp[1]);
    }
    return 0;
}

 

 

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/hackbuteer1/article/details/7369630
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞