POJ 3463

//题目类型;最短路-—最短路和相差一个单位的次短路的条数和
//本题关键在于理解Dijkstra的贪心思想
解题思路:
本题若开始直接在Dijkstra中加入针对加1的递推式, 必须在Dijkstra的过程中加入DFS, 很繁琐. 改换求次短路, 然后判断次短路是否比最短路长1.
解法一、A*求第K短路,把前面K条路都求出来,pku 2449 ,但是据说这个题的最后答案超过10^8,把路全部找出来肯定会爆priority_queue
解法二、
改进Dijkstra算法,。将状态扩展到二维,第一维仍然是顶点编号,第二维的长度为2,分别用于记录最短路和次短路。
这样的数据有两个,dist[][2]记录距离,cnt[][2]计数。

更新状态时:
1)新值小于最短路径长:更新最短路径长,计数;次短路径长,计数
2)新值等于最短路径长:更新最短路径计数
3)新值大于最短路径长,小于次短路径长:更新次短路径长,计数
4)新值等于次短路径长:更新次短路径计数

值得注意的是,题目图有重边,所以不能用邻接矩阵存储。
 本题可以与UESTC 1053 Shortest road(只求最短路的条数,但最短路中的路径只有一条不同即可),HDU 1459(只求最短路的条数,但是不同最短路的最短路的不能包含相同的路)。本题和UESTC 1053 Shortest road最短路均可重复,只有一条不同即可。
#include <iostream>
//#include <conio.h>
#include <queue>
#include <vector>
using namespace std;
#define marray 10001
#define narray 1001
const int maxData = 0x7fffffff;
typedef struct edge
{
    int v;
    int w;
}edge;
int n,m;
int src,des;
int edgenum;
vector<edge> adj[narray];
bool final[narray][2];
int d[narray][2];
int cnt[narray][2];
int Dij()
{
     int i,j,k,v;
     for(i=1;i<=n;++i)
     {
         d[i][0] = maxData;
         d[i][1] = maxData;     
         cnt[i][0] = maxData;
         cnt[i][1] = maxData;
         final[i][0] = false;
         final[i][1] = false;
     }    
     cnt[src][0] = 1;
     d[src][0] = 0;
     //final[src][0] = true; 此处不能将final[src][0]的值赋值为true,因为本题使用邻接表实现,d[i][0],d[i][1]没有初始化为与源点的距离
     for(i=1;i<2*n;++i)
     {
         int temp = maxData;
         v = -1;
         for(j=1;j<=n;++j)
         {
             if(!final[j][0] && d[j][0]<temp)
             {
                 v = j;
                 k = 0;
                 temp = d[j][0];
             }
             else if(!final[j][1] && d[j][1]<temp)
             {
                  v = j;
                  k = 1;
                  temp = d[j][1];
             }
         }
         if(v==-1)
             break;
         final[v][k] = true;
         for(j=0;j<adj[v].size();++j)
         {
             int u = adj[v][j].v;
             int w = adj[v][j].w;
             if(d[u][0]>temp+w)
             {
                 d[u][1] = d[u][0];
                 d[u][0] = temp+w;
                
                 cnt[u][1] = cnt[u][0];
                 cnt[u][0] = cnt[v][k];                
             }
             else if(d[u][0]==temp+w)
             {
                  cnt[u][0]+=cnt[v][k];
             }
             else if(d[u][1]>temp+w)
             {
                   d[u][1] = temp+w;
                   cnt[u][1] = cnt[v][k];
             }
             else if(d[u][1]==temp+w)
             {
                   cnt[u][1] += cnt[v][k];
             }
                 
         }
     }
     int num = cnt[des][0];    
     if(d[des][0]+1==d[des][1])           //判断最短路和次短路是否相差一个单位
         num += cnt[des][1];
     return num;
}
int main()
{
    //freopen("1.txt","r",stdin);
    int i,j;
    int t;
    int start,end,weight;
    edge tempedge;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;++i)
        {
             adj[i].clear();
        }
        for(i=1;i<=m;++i)
        {
            scanf("%d%d%d",&start,&end,&weight);
            tempedge.v = end;
            tempedge.w = weight;
            adj[start].push_back(tempedge);
        }             
        scanf("%d%d",&src,&des);
        printf("%d\n",Dij());
    }
    //getch();
    return 0;
}

posted @ 2010-06-05 21:51  北海小龙  阅读(1374)  评论(0编辑  收藏  举报