• MST:Roadblocks(POJ 3255)


                     

                       路上的石头

      题目大意:某个街区有R条路,N个路口,道路双向,问你从开始(1)到N路口的次短路经长度,同一条边可以经过多次。

      这一题相当有意思,现在不是要你找最短路径,而是要你找次短路经,而且次短路经同一条可以经过多次,用Dijkstra的方法最短路是只会经过一条边的。

      但是别急,我们次短路经也是建立在最短路径上的,那么其实我们完全可以用最短路径的算法来解决这个问题,但是要修改一下算法,这里用Dijkstra算法(没有负边),我们设定两个区域,一个是最短路径区域,一个是次短路径区域,问题来了,怎么更新这两个区域呢?

      首先最短路径区域更新的方法是一样的,次短路经怎么办?我们可以根据次短路经是上一条最短路径+本次路径次短边来完成这个操作,但是上一次最短路径可以是多条,所以我们就要想想办法了,其实在这里我们可以把以前我们熟悉的Dijkstra算法的known域去掉,那样我们就可以不用受“节点只能经过一次”的限制了,而且也实现了一条边可以经过多次,而且我们会把节点多次入堆,节点不再是纯粹的单节点了,而是一个临时节点(即最短路径和次短路经都是临时的,但是我们只用维护最短的就可以了),实现对路径的选择(而不是节点)

      那么更新的时候我们围绕次短路经来裁剪选择就可以了,当目标节点的当前次短路经比临时的最短路径还要大,那就不必搜索了。

      所以这题千万不能用以前那个旧方法,我就生搬硬套,没有考虑到次短路经不能第一时间维护,所以导致多次wa,心疼

      

      1 #include <iostream>
      2 #include <functional>
      3 #include <algorithm>
      4 #include <queue>
      5 #define MAX 5004
      6 #define MAX_E 100005
      7 
      8 using namespace std;
      9 typedef int Position;
     10 
     11 typedef struct map//向前边方法储存邻接表
     12 {
     13     int cost;
     14     Position to;
     15     int next;
     16 
     17 }Edge;
     18 typedef struct node_
     19 {
     20     Position point;
     21     Position v;
     22     int cost;//最短路径
     23     bool operator<(const node_ &x)const
     24     {
     25         return cost > x.cost;
     26     }
     27 
     28 }Node;
     29 
     30 static Edge edge[MAX_E * 2];
     31 static Node head[MAX];
     32 static int Dist_Min[MAX], Dist_last_min[MAX];
     33 
     34 void Dijkstra(const int);
     35 void Swap(int *const, int *const);
     36 
     37 int main(void)
     38 {
     39     int Node_Sum, Road_Sum, from, to, tmp_cost;
     40     while (~scanf("%d%d", &Node_Sum, &Road_Sum))
     41     {
     42 
     43         for (int i = 1; i <= Node_Sum; i++)
     44         {
     45             head[i].v = i;
     46             head[i].point = -1;
     47         }
     48         for (int i = 0; i < Road_Sum * 2; i += 2)//向前边法储存邻接表
     49         {
     50             scanf("%d%d%d", &from, &to, &tmp_cost);
     51 
     52             edge[i].next = head[from].point; edge[i].to = to; edge[i].cost = tmp_cost;
     53             head[from].point = i;
     54             edge[i + 1].next = head[to].point; edge[i + 1].to = from; edge[i + 1].cost = tmp_cost;
     55             head[to].point = i + 1;
     56         }
     57         Dijkstra(Node_Sum);
     58     }
     59     return 0;
     60 }
     61 
     62 void Swap(int *const a, int *const b)
     63 {
     64     *a ^= *b;
     65     *b ^= *a;
     66     *a ^= *b;
     67 }
     68 
     69 void Dijkstra(const int Node_Sum)
     70 {
     71     int out, v, k, dist, d_out;
     72     Edge e_tmp; Node Node_tmp;
     73 
     74     fill(Dist_last_min + 1, Dist_last_min + Node_Sum + 1, 0x7fffffff);
     75     fill(Dist_Min + 1, Dist_Min + Node_Sum + 1, 0x7fffffff);
     76 
     77     priority_queue<Node> que;
     78     Dist_Min[1] = 0;
     79     Node_tmp.v = 1; Node_tmp.cost = 0; Node_tmp.point = head[1].point;
     80     que.push(Node_tmp);
     81 
     82     while (!que.empty())//Diskstra算法还可以找次短路
     83     {
     84         Node_tmp = que.top(); que.pop();
     85 
     86         out = Node_tmp.v; d_out = Node_tmp.cost;
     87         if (d_out > Dist_last_min[out]) continue;//千万不要简单的就直接用以前的方法固定min_dist,因为
     88         for (k = Node_tmp.point; k != -1; k = edge[k].next)
     89         {
     90             e_tmp = edge[k]; v = e_tmp.to;
     91             dist = d_out + e_tmp.cost;
     92             if (dist < Dist_Min[v])
     93             {
     94                 Swap(&dist, &Dist_Min[v]);//注意一定是交换!
     95                 Node_tmp.v = v; Node_tmp.cost = Dist_Min[v]; Node_tmp.point = head[v].point;
     96                 que.push(Node_tmp);
     97             }
     98             if (dist < Dist_last_min[v] && dist > Dist_Min[v])
     99             {
    100                 Dist_last_min[v] = dist;
    101                 Node_tmp.v = v; Node_tmp.cost = Dist_last_min[v]; Node_tmp.point = head[v].point;
    102                 que.push(Node_tmp);//这里会造成v多次入堆,需要做特判
    103             }
    104         }
    105     }
    106     printf("%d
    ", Dist_last_min[Node_Sum]);
    107 }

             

  • 相关阅读:
    JavaSE-28 hashCode()方法、equals()方法和==相关概念
    设计模式:命令模式(Command Pattern)
    Spring-02 Java配置实现IOC
    Spring-01 注解实现IOC
    [功能帮助类] 最新的Functions 类 (转载)
    C# DbHelperSQL,操作不同的数据库帮助类 (转载)
    C# DbHelperSQLP,操作不同的数据库帮助类 (转载)
    C# DbHelperSQLite,SQLite数据库帮助类 (转载)
    C#DbHelperOra,Oracle数据库帮助类 (转载)
    C#DbHelperOleDb,Access数据库帮助类 (转载)
  • 原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/4945979.html
Copyright © 2020-2023  润新知