zoukankan      html  css  js  c++  java
  • POJ3463 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 }
  • 相关阅读:
    eclipse开发安卓 发短信打电话发送邮件功能
    关于springboot连接数据库是报错
    --Angular-01-关于angular-tree-component--
    --外功篇-Less的学习日志-01-辅助理解Less--
    --兵器谱--git学习记录帖--
    --兵器谱--git初体验--
    --算法恩仇录--实战篇--力扣(LeetCode)--022-括号生成--
    --算法恩仇录--实战篇--力扣(LeetCode)--011-盛水最多的容器--
    --算法恩仇录--实战篇--力扣(LeetCode)--006-Z字形变换--
    --算法恩仇录--实战篇--力扣(LeetCode)--005-最长回文子串--
  • 原文地址:https://www.cnblogs.com/zhsl/p/2873309.html
Copyright © 2011-2022 走看看