zoukankan      html  css  js  c++  java
  • Remmarguts' Date POJ

    "Good man never makes girls wait or breaks an appointment!" said the mandarin duck father. Softly touching his little ducks' head, he told them a story.

    "Prince Remmarguts lives in his kingdom UDF – United Delta of Freedom. One day their neighboring country sent them Princess Uyuw on a diplomatic mission."

    "Erenow, the princess sent Remmarguts a letter, informing him that she would come to the hall and hold commercial talks with UDF if and only if the prince go and meet her via the K-th shortest path. (in fact, Uyuw does not want to come at all)"

    Being interested in the trade development and such a lovely girl, Prince Remmarguts really became enamored. He needs you - the prime minister's help!

    DETAILS: UDF's capital consists of N stations. The hall is numbered S, while the station numbered T denotes prince' current place. M muddy directed sideways connect some of the stations. Remmarguts' path to welcome the princess might include the same station twice or more than twice, even it is the station with number S or T. Different paths with same length will be considered disparate.

    Input

    The first line contains two integer numbers N and M (1 <= N <= 1000, 0 <= M <= 100000). Stations are numbered from 1 to N. Each of the following M lines contains three integer numbers A, B and T (1 <= A, B <= N, 1 <= T <= 100). It shows that there is a directed sideway from A-th station to B-th station with time T.

    The last line consists of three integer numbers S, T and K (1 <= S, T <= N, 1 <= K <= 1000).

    Output

    A single line consisting of a single integer number: the length (time required) to welcome Princess Uyuw using the K-th shortest path. If K-th shortest path does not exist, you should output "-1" (without quotes) instead.

    Sample Input

    2 2
    1 2 5
    2 1 4
    1 2 2
    

    Sample Output

    14

    题意:n个点,m条边的有向图,每个点可以多次抵达,给出s、t、k,求从s到t的第k短路
    思路:求最短路最常用的就是堆优化的dijkstra,那么很容易想到的一种写法:用dijkstra,当t第k次出现,那就是第k短路;但是如果有些状态当前值很小,但是未来值很大,优先队列就会先去扩展这个状态,
    这样的情况多了,就会导致搜索量增大。

    优先队列是以当前所走过的路程最小的为优先的,它并不知道该状态后面的情况,所有排序并不是很完美,这时候我们就可以想到为其加入评估函数(估计该状态后面所需的路程),并且评估值<=实际值。
    这样我们使用优先队列是,将(该状态花费+评估值,节点)送入队列,取出时是总体评估最小,也就是不仅考虑了已走路程,顺便考虑了其后续可能路程,取出之后,花费-该点评估值==实际花费,然后扩展该状态,
    将(状态实际花费+下个点评估值+该路径长度)送入队列
    这样当t出项k次时出现的就是第k短路
    因为 评估值<=实际值,所以状态花费+评估值 <= 状态花费+实际值 == s(总花费),所以最优值肯定会在次优值之前出栈,(虽然之前的优先队列也这样)而且因为评估了后续所需,所以不会出现前小后大的
    非最优花费大量在队列前扩展,尽量让其直接将最优解排在队列前扩展,少扩展其他分支。

    那么这个题的评估函数怎么求呢,因为我们是求到t的k短路,那么我们就把所有点到t的对短路当成评估函数,也就是以t为原点,求一遍最短路,刚好这个值可以反应未来变化的趋势和相对大小关系

    注:该题当s==t时,0并不是第一条路
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<queue>
     4 #include<string.h>
     5 using namespace std;
     6 
     7 int n,m;
     8 typedef pair<int,int>p;
     9 struct E
    10 {
    11     int x,y,val;
    12     int next;
    13     E(int x=0,int y=0,int val=0,int next=-1):x(x),y(y),val(val),next(next){}
    14 }edge[100005];
    15 int head[1005];
    16 int cnt;
    17 E t_edge[100005];
    18 int t_head[1005];
    19 int t_cnt;
    20 int f[1005];
    21 int ans[1005];
    22 void add(int x,int y,int val)
    23 {
    24     edge[++cnt] = E(x,y,val,head[x]);
    25     head[x] = cnt;
    26     t_edge[++t_cnt] = E(y,x,val,t_head[y]);
    27     t_head[y] = t_cnt;
    28 }
    29 
    30 void get_f(int t)
    31 {
    32     memset(f,0x3f,sizeof(f));
    33     priority_queue<p,vector<p>,greater<p> >que;
    34     while(!que.empty())que.pop();
    35     que.push(p(0,t));
    36     while(!que.empty())
    37     {
    38         p tmp = que.top();
    39         que.pop();
    40         int now = tmp.second;
    41         int cost = tmp.first;
    42         if(f[now] != 0x3f3f3f3f)continue;
    43         f[now] = cost;
    44         for(int i=t_head[now];i!=-1;i=t_edge[i].next)
    45         {
    46             if(f[now] + t_edge[i].val < f[t_edge[i].y])
    47             {
    48 
    49                 que.push(p(f[now] + t_edge[i].val,t_edge[i].y));
    50             }
    51         }
    52     }
    53 }
    54 
    55 int cal(int s,int t,int k)
    56 {
    57     priority_queue<p,vector<p>,greater<p> >que;
    58     while(!que.empty())que.pop();
    59     que.push(p(f[s],s));
    60     memset(ans,0x3f,sizeof(ans));
    61     int cnt = 0;
    62     if(s == t)k++;
    63     if(f[s] == 0x3f3f3f3f)return -1;
    64     while(!que.empty())
    65     {
    66         p tmp = que.top();
    67         que.pop();
    68         int now = tmp.second;
    69         int cost = tmp.first - f[now];
    70         if(now == t)
    71         {
    72             cnt++;
    73             if(cnt == k)return cost;
    74         }
    75         for(int i=head[now];i!=-1;i=edge[i].next)
    76         {
    77             que.push(p(cost+edge[i].val+f[edge[i].y],edge[i].y));
    78         }
    79     }
    80     return -1;
    81 }
    82 
    83 int main()
    84 {
    85     scanf("%d%d",&n,&m);
    86     memset(head,-1,sizeof(head));
    87     memset(t_head,-1,sizeof(t_head));
    88     for(int i=1;i<=m;i++)
    89     {
    90         int u,v,k;
    91         scanf("%d%d%d",&u,&v,&k);
    92         add(u,v,k);
    93     }
    94     int s,t,k;
    95     scanf("%d%d%d",&s,&t,&k);
    96     get_f(t);
    97     printf("%d
    ",cal(s,t,k));
    98 }
    View Code
     
  • 相关阅读:
    C# layui组件Dtree简单使用
    利用FormsAuthentication.RedirectFromLoginPage进行身份验证
    Mono for Android (4)-- 图片转为二进制,二进制转回图片
    Android Bitmap详细介绍
    Mono for Android (3)-- AbsoluteLayout、FrameLayout、LinearLayout、RelativeLayout、TableLayout
    Mono for Android (2)-- Android应用程序初认识
    iOS之浅谈纯代码控制UIViewController视图控制器跳转界面的几种方法
    JAVA学习笔记(六)--简单抽奖系统
    第五周JAVA学习笔记(五)
    第四周JAVA学习笔记(四)
  • 原文地址:https://www.cnblogs.com/iwannabe/p/10609823.html
Copyright © 2011-2022 走看看