• HDU 4479 权递增的最短路问题


    题目大意:

    找一条节点 1 到节点 N 的最短路,保证这条路上每一条边都比前一条边长

    dp[i] 表示在当前状态下1到i的最小值

    先将所有边根据边的长度排一个序,再每次取出同一段相同长度的边去更新当前图中的每一个点可以更新的dp值,当然我们不能不能因为这相同的边长相互影响,所以不能边找边的同时边松弛dp值,因为可能 1-2:1  2-3:1,也就是说第一次其实不能由1到3这个点,但是你先更新1-2,那么2-3会因为2的dp值存在而可以松弛,所以,先找到所有可行的能进行迟缓的边记录在rec[]数组中,再把里面所有的边弛缓一遍

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 using namespace std;
     6 const int N = 10005;
     7 typedef long long LL;
     8 LL dp[N];
     9 int n , m , k;
    10 
    11 struct Path{
    12     int x,y,d;
    13     bool operator<(const Path &m)const{
    14         return d < m.d;
    15     }
    16 }p[100005];
    17 
    18 struct Rec{
    19     int x,y;
    20     LL d;
    21     Rec(int x=0,int y=0,LL d=0):x(x),y(y),d(d){}
    22 }rec[100005];
    23 
    24 void update(int l , int r)
    25 {
    26     int t = 0;
    27 
    28     for(int i=l;i<=r;i++){
    29         int u = p[i].x , v = p[i].y;
    30         if(dp[u] >= 0 && (dp[v] > dp[u] + p[i].d || dp[v] < 0))
    31         {
    32             rec[t++] = Rec(u,v, dp[u] + p[i].d);
    33         }
    34         if(dp[v] >= 0 && (dp[u] > dp[v] + p[i].d || dp[u] < 0))
    35         {
    36             rec[t++] = Rec(v,u, dp[v] + p[i].d);
    37         }
    38     }
    39 
    40     for(int i=0;i<t;i++){
    41         int u = rec[i].x , v = rec[i].y;
    42         if(dp[v] > rec[i].d || dp[v] < 0)
    43         {
    44             dp[v] = rec[i].d;
    45         }
    46     }
    47 }
    48 
    49 void add_edge(int x,int y,int d)
    50 {
    51     p[k].x = x , p[k].y = y , p[k++].d = d;
    52 }
    53 
    54 void solve()
    55 {
    56     sort(p,p+k);
    57     memset(dp,-1,sizeof(dp));
    58     dp[1] = 0;
    59     int l=0;
    60     for(int r=1 ; r<k;r++){
    61         if(p[r].d != p[r-1].d){
    62             update(l , r-1);
    63             l=r;
    64         }
    65     }
    66     update(l,k-1);
    67     if(dp[n] < 0)
    68         puts("No answer");
    69     else
    70         printf("%I64d
    ",dp[n]);
    71 }
    72 
    73 int main()
    74 {
    75    // freopen("test.in","rb",stdin);
    76 
    77     int T,a,b,d;
    78     scanf("%d",&T);
    79     while(T--){
    80         scanf("%d%d",&n,&m);
    81 
    82         k=0;
    83         memset(G , -1 , sizeof(G));
    84         for(int i=0;i<m;i++){
    85             scanf("%d%d%d",&a,&b,&d);
    86             add_edge(a,b,d);
    87         }
    88         solve();
    89     }
    90     return 0;
    91 }
  • 相关阅读:
    JAVA 桥接模式
    字模生成/提取原理
    const修饰指针
    BMP格式分析
    [转载]在.Net中使用SMTP发送邮件
    [转载]MD5加密解密
    四十二。java
    四十四。java
    四十一。复习第十二章内容
    三十六。文件流
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4041396.html
Copyright © 2020-2023  润新知