POJ-3463 Sightseeing 最短路+记忆化搜索

  题目链接:http://poj.org/problem?id=3463

  给定一有向图,要你求出最短路的数目和最短路长度+1的数目。

  比较方便的办法就是在Dijkstra的时候就直接把数目求出来,Dijkstra基于贪心的思想,一个点向其它点松弛后,那么就不会有后继点向此点松弛,因此可以来统计总共有多少条路径:1,更新v点最短距离后,v点路径数目等于u点路径数目  2,如果到点u到点v有等于v点当前的最短路径,则v点的路径数目加上u点的路径数目。求最短路长度+1的数目实际上就是求次短路的数目,如果次短路长度刚好比最短路长度大1,那么就是答案的一部分。注意到这个次短路比较特殊,之比最短路大1,因此次短路的前继节点距离只可能是最短的或者次短的,因此可以用d[N][2],cou[N][2],来统计:

      1,如果d[u][0]+w<d[u][0],分别更新v点的最短路和次短路

      2,如果d[u][0]+w==d[u][0],那么v点的最短路数加上u点的最短路数

      3,如果d[u][k]+w<d[u][1],更新v点的次短路数(根据k来定)

      4,如果d[u][k]+w==d[u][1],那么v点的次短路数加上u点的最短路数或者次短路数(根据k来定)

  最短路长度+1的数目还可以用记忆化搜索来求解,转移方程:f[u]=sum{f[v] | d[u]-w=d[v]} + sum{cou[v] | d[u]-w+1=d[v]}。要注意建立反向边!

Dijkstra+记忆化搜索:

  1 //STATUS:C++_AC_32MS_532KB

  2 #include<stdio.h>

  3 #include<stdlib.h>

  4 #include<string.h>

  5 #include<math.h>

  6 #include<iostream>

  7 #include<string>

  8 #include<algorithm>

  9 #include<vector>

 10 #include<queue>

 11 #include<stack>

 12 using namespace std;

 13 #define LL __int64

 14 #define pii pair<int,int>

 15 #define Max(a,b) ((a)>(b)?(a):(b))

 16 #define Min(a,b) ((a)<(b)?(a):(b))

 17 #define mem(a,b) memset(a,b,sizeof(a))

 18 #define lson l,mid,rt<<1

 19 #define rson mid+1,r,rt<<1|1

 20 const int N=1010,M=1000000,INF=0x3f3f3f3f,MOD=1999997;

 21 const LL LLNF=0x3f3f3f3f3f3f3f3fLL;

 22 const double DNF=100000000;

 23 

 24 struct Edge{

 25     int u,v,w;

 26 }e[N*10*2];

 27 int first[N],next[N*10*2],d[N],cou[N],cou2[N];

 28 int T,s,f,n,m,mt;

 29 

 30 void adde(int a,int b,int c)

 31 {

 32     e[mt].u=a,e[mt].v=b;e[mt].w=c;

 33     next[mt]=first[a],first[a]=mt++;

 34     e[mt].u=b,e[mt].v=a;e[mt].w=c;

 35     next[mt]=first[b],first[b]=mt++;

 36 }

 37 

 38 int dijkstra(int s)

 39 {

 40     int i,u;

 41     pii t;

 42     priority_queue<pii,vector<pii>,greater<pii> > q;

 43     mem(d,0x3f);d[s]=0;

 44     cou[s]=1;

 45     q.push(make_pair(d[s],s));

 46     while(!q.empty()){

 47         t=q.top();q.pop();

 48         u=t.second;

 49         if(t.first!=d[u])continue;

 50         for(i=first[u];i!=-1;i=next[i]){

 51             if((i&1)==0)continue;

 52             if(d[u]+e[i].w<d[e[i].v]){

 53                 cou[e[i].v]=cou[u];

 54                 d[e[i].v]=d[u]+e[i].w;

 55                 q.push(make_pair(d[e[i].v],e[i].v));

 56             }

 57             else if(d[u]+e[i].w==d[e[i].v])cou[e[i].v]+=cou[u];

 58         }

 59     }

 60     return 1;

 61 }

 62 

 63 int dfs(int u)

 64 {

 65     if(cou2[u]!=-1)return cou2[u];

 66     cou2[u]=0;

 67     int i;

 68     for(i=first[u];i!=-1;i=next[i]){

 69         if(i&1)continue;

 70         if(d[u]-e[i].w==d[e[i].v])

 71             cou2[u]+=dfs(e[i].v);

 72         else if(d[u]-e[i].w+1==d[e[i].v])

 73             cou2[u]+=cou[e[i].v];

 74     }

 75     return cou2[u];

 76 }

 77 

 78 int main()

 79 {

 80  //   freopen("in.txt","r",stdin);

 81     int i,j,a,b,c,ans;

 82     scanf("%d",&T);

 83     while(T--)

 84     {

 85         mt=0;

 86         mem(first,-1);

 87         mem(cou2,-1);

 88         scanf("%d%d",&n,&m);

 89         for(i=0;i<m;i++){

 90             scanf("%d%d%d",&a,&b,&c);

 91             adde(a,b,c);

 92         }

 93         scanf("%d%d",&s,&f);

 94 

 95         dijkstra(f);

 96         ans=cou[s];

 97         ans+=dfs(s);

 98 

 99         printf("%d\n",ans);

100     }

101     return 0;

102 }

Dijkstra:

 1 //STATUS:C++_AC_47MS_964KB

 2 #include<stdio.h>

 3 #include<stdlib.h>

 4 #include<string.h>

 5 #include<math.h>

 6 #include<iostream>

 7 #include<string>

 8 #include<algorithm>

 9 #include<vector>

10 #include<queue>

11 #include<stack>

12 using namespace std;

13 #define LL __int64

14 #define pii pair<int,int>

15 #define Max(a,b) ((a)>(b)?(a):(b))

16 #define Min(a,b) ((a)<(b)?(a):(b))

17 #define mem(a,b) memset(a,b,sizeof(a))

18 #define lson l,mid,rt<<1

19 #define rson mid+1,r,rt<<1|1

20 const int N=1010,M=1000000,INF=0x3f3f3f3f,MOD=1999997;

21 const LL LLNF=0x3f3f3f3f3f3f3f3fLL;

22 const double DNF=100000000;

23 

24 struct Node{

25     int d,u,flag;

26     bool operator < (const Node &oth) const{

27         return d>oth.d;

28     }

29 };

30 struct Edge{

31     int u,v,w;

32 }e[N*10];

33 int first[N],next[N*10],d[N][2],cou[N][2];

34 int T,s,f,n,m,mt;

35 

36 void adde(int a,int b,int c)

37 {

38     e[mt].u=a,e[mt].v=b;e[mt].w=c;

39     next[mt]=first[a],first[a]=mt++;

40 }

41 

42 int dijkstra(int s)

43 {

44     int i,u,v,w,k,dis;

45     Node t;

46     priority_queue<Node> q;

47     mem(d,0x3f);d[s][0]=d[s][1]=0;

48     cou[s][0]=cou[s][1]=1;

49     t.d=0,t.u=s,t.flag=0;

50     q.push(t);

51     while(!q.empty()){

52         t=q.top();q.pop();

53         u=t.u;dis=t.d;k=t.flag;

54         if(dis!=d[u][k])continue;

55         for(i=first[u];i!=-1;i=next[i]){

56             v=e[i].v;w=e[i].w;

57             if(dis+w<d[v][0]){

58                 cou[v][1]=cou[v][0];

59                 cou[v][0]=cou[u][0];

60                 d[v][1]=d[v][0];

61                 d[v][0]=dis+w;

62                 q.push(Node{d[v][0],v,0});

63                 q.push(Node{d[v][1],v,1});

64             }

65             else if(dis+w==d[v][0])cou[v][0]+=cou[u][0];

66             else if(dis+w<d[v][1]){

67                 d[v][1]=dis+w;

68                 cou[v][1]=cou[u][k];

69                 q.push(Node{d[v][1],v,1});

70             }

71             else if(dis+w==d[v][1])cou[v][1]+=cou[u][k];

72         }

73     }

74     return cou[f][0]+(d[f][1]==d[f][0]+1?cou[f][1]:0);

75 }

76 

77 int main()

78 {

79  //   freopen("in.txt","r",stdin);

80     int i,j,a,b,c;

81     scanf("%d",&T);

82     while(T--)

83     {

84         mt=0;

85         mem(first,-1);

86         scanf("%d%d",&n,&m);

87         for(i=0;i<m;i++){

88             scanf("%d%d%d",&a,&b,&c);

89             adde(a,b,c);

90         }

91         scanf("%d%d",&s,&f);

92 

93         printf("%d\n",dijkstra(s));

94     }

95     return 0;

96 }

 

你可能感兴趣的:(poj)