• UVA 10917 Walk Through the Forest(dijkstra+DAG上的dp)


    用新模板阿姨了一天,换成原来的一遍就ac了= =

    题意很重要。。最关键的一句话是说:若走A->B这条边,必然是d[B]<d[A],d[]数组保存的是各点到终点的最短路。

    所以先做dij,由d[B]<d[A]可知,所走的路径上各点的d[]值是由大到小的,即是一个DAG,从而决定用记忆化搜索查找总的路径数。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 const int MAXN=1111;
     7 const int INF =0x0fffff;
     8 
     9 int G[MAXN][MAXN],vis[MAXN],d[MAXN],n;
    10 int mark[MAXN],dp[MAXN];
    11 
    12 void dij(int n)
    13 {
    14     memset(vis,0,sizeof(vis));
    15     for(int i=1;i<=n;i++)
    16         if(i==2)d[i]=0;
    17         else d[i]=INF;
    18     for(int i=0;i<n;i++)
    19     {
    20         int x,m=INF;
    21         for(int y=1;y<=n;y++)
    22         if(!vis[y]&&d[y]<m){
    23             x=y;
    24             m=d[x];
    25         }
    26         vis[x]=1;
    27         for(int y=1;y<=n;y++)
    28             if(d[y]>d[x]+G[x][y])
    29                 d[y]=d[x]+G[x][y];
    30     }
    31 }
    32 
    33 int dfs(int u,int ed)
    34 {
    35     if(mark[u])
    36         return dp[u];
    37     mark[u]=1;
    38     if(u==ed){
    39         dp[u]=1;
    40         return dp[u];
    41     }
    42     int ans=0;
    43     for(int i=1;i<=n;i++)
    44     {
    45         if(G[u][i]!=INF&&d[i]<d[u])
    46             ans+=dfs(i,ed);
    47     }
    48     dp[u]=ans;
    49     return dp[u];
    50 }
    51 
    52 int main()
    53 {
    54     int m,u,v,c;
    55     while(~scanf("%d",&n))
    56     {
    57         if(!n)
    58             return 0;
    59         scanf("%d",&m);
    60         for(int i=1;i<=n;i++)
    61             for(int j=1;j<=n;j++)
    62                 if(i==j)G[i][j]=0;
    63                 else G[i][j]=INF;
    64         for(int i=0;i<m;i++)
    65         {
    66             scanf("%d%d%d",&u,&v,&c);
    67             if(G[u][v]>c)
    68                 G[u][v]=G[v][u]=c;
    69         }
    70 
    71         dij(n);
    72 
    73         memset(mark,0,sizeof(mark));
    74         printf("%d
    ",dfs(1,2));
    75 
    76     }
    77     return 0;
    78 }
    View Code

     后记:

        回顾这道题,想到了一个问题:两点之间可以存在重边,用邻接表存储,同一条路线会被重复计算。e.g:1->2->3,即d[1]>d[2]>d[3],如果1->2有两条路,那么这两条路都符合d[1]>d[2]的条件。虽然题目中描述Jimmy想从不同的路线经过,而事实上应该是不算重边的。

  • 相关阅读:
    🔨FFmpeg 转换至 MP4 视频格式
    🔨Ubuntu Linux '门' '复' 显示不标准
    🔨Youtube-dl 开代理搭配 Aria2 多线程加速下载
    📔 如何用英语的思维来思考 How to THINK in English
    🚀 sublime 加速软件下载
    🚀 snap 代理
    🚀 Chocolatey 代理
    🔨 Deepin V20 软件及遇到的问题
    💿 npm 换源 (转载)
    🔨FFmpeg 合并视频
  • 原文地址:https://www.cnblogs.com/zstu-abc/p/3251815.html
Copyright © 2020-2023  润新知