zoukankan      html  css  js  c++  java
  • POJ

    题目链接

    题意:求有向图从s点到t点的第k短路,每个点可以重复经过。

    解法:建一个正向图和一个反向图,先用Dijkstra求出反向图中从t点到其他点的最短距离dis,再用A*算法求出第k短路。

    A*求第k短路的方法:与Dijkstra算法类似,设结点nd(u,g)表示当前所在点为u且从s到u经过的长度为g的结点(路径),则以g+dis[u]为权值放进优先队列,每次选择权值最小的结点进行扩展,直至t点第k次出队。

    算是A*算法的一道入门题吧。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 
     5 using namespace std;
     6 const int N=1000+10,M=1e5+10;
     7 const int inf=0x3f3f3f3f;
     8 struct E {
     9     int v,c,nxt;
    10 } e[M<<1];
    11 int head1[N],head2[N],dis[N],vis[N],ne;
    12 int n,m;
    13 
    14 struct cmp {
    15     bool operator()(int a,int b)const {
    16         return dis[a]>dis[b];
    17     }
    18 };
    19 
    20 struct nd {
    21     int u,g;
    22     bool operator<(const nd& b)const {
    23         return g+dis[u]>b.g+dis[b.u];
    24     }
    25 };
    26 
    27 void Dij(int s) {
    28     priority_queue<int,vector<int>,cmp> q;
    29     memset(vis,0,sizeof vis);
    30     memset(dis,inf,sizeof dis);
    31     dis[s]=0;
    32     q.push(s);
    33     while(!q.empty()) {
    34         int u=q.top();
    35         q.pop();
    36         if(vis[u])continue;
    37         vis[u]=1;
    38         for(int i=head2[u]; ~i; i=e[i].nxt) {
    39             int v=e[i].v,c=e[i].c;
    40             if(dis[u]+c<dis[v]) {
    41                 dis[v]=dis[u]+c;
    42                 q.push(v);
    43             }
    44         }
    45     }
    46 }
    47 
    48 int Astar(int s,int t,int k) {
    49     int cnt=0;
    50     if(s==t)cnt--;
    51     priority_queue<nd> q;
    52     q.push({s,0});
    53     while(!q.empty()) {
    54         int u=q.top().u,g=q.top().g;
    55         q.pop();
    56         if(u==t)++cnt;
    57         if(cnt==k)return g;
    58         for(int i=head1[u]; ~i; i=e[i].nxt) {
    59             int v=e[i].v,c=e[i].c;
    60             q.push({v,g+c});
    61         }
    62     }
    63     return -1;
    64 }
    65 
    66 int main() {
    67     memset(head1,-1,sizeof head1);
    68     memset(head2,-1,sizeof head2);
    69     ne=0;
    70     scanf("%d%d",&n,&m);
    71     while(m--) {
    72         int u,v,c;
    73         scanf("%d%d%d",&u,&v,&c);
    74         e[ne]=(E) {v,c,head1[u]},head1[u]=ne++;
    75         e[ne]=(E) {u,c,head2[v]},head2[v]=ne++;
    76     }
    77     int s,t,k;
    78     scanf("%d%d%d",&s,&t,&k);
    79     Dij(t);
    80     printf("%d
    ",Astar(s,t,k));
    81     return 0;
    82 }
  • 相关阅读:
    Cocos2d-x开发实例:使用Lambda 表达式
    Cocos2d-x实例:单点触摸事件
    Cocos2d-x中触摸事件
    Cocos2d-x开发实例介绍帧动画使用
    Cocos2d-x开发实例介绍特效演示
    c++ 类型转换
    boost的编译
    c/c++二级指针动态开辟内存
    基于RANSAC的点云面分割算法
    点到平面直线的距离和空间直线的距离
  • 原文地址:https://www.cnblogs.com/asdfsag/p/10260793.html
Copyright © 2011-2022 走看看