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 }

 

posted @ 2013-01-23 16:03  zhsl  阅读(280)  评论(0编辑  收藏  举报