• POJ 2449 Remmarguts' Date【K短路问题,A*、dijkstra】



    POJ 2449 Remmarguts' Date
    http://poj.org/problem?id=2449
    算法核心:A*、dijkstra
    大意:求有向图中从s到t的k短路
    分析:
    1.用dijkstra逆向计算出所有点到t的最短距离dis[i]
    2.建立估价函数 f(i)= g(i)+h(i)
      其中g(i)为从s到i的实际距离,h(i)为从i到t的最短路dis[i]
    3.使用上述估计函数用A*算法从s点出发BFS全图,用visited[i]表示点i的出队次数。
      当visited[i]=k时,即找到从s到t的k短路为f(i)
      其间若visited[i]>k则放弃该点

    4.注意:若s==t,需 k+1;

    View Code
    #include<stdio.h>
    #include
    <string.h>
    #include
    <queue>
    usingnamespace std;
    constint N =1000+1;
    constint M =100000+1;
    struct Edge
    {
    int from,to;
    int dis;
    Edge
    *next;
    }
    *ed[N],edge[M],*re[N],redge[M];
    int ednum;
    int dis[N];
    int visited[N];
    void init(int n)
    {
    int i;
    for(i=0;i<n;i++)
    {
    ed[i]
    =NULL;
    re[i]
    =NULL;
    }
    }
    void addEdge(int from,int to,int dis)
    {
    Edge
    *ptr =&edge[ednum];
    ptr
    ->from = from;
    ptr
    ->to = to;
    ptr
    ->dis = dis;
    ptr
    ->next = ed[from];
    ed[from]
    =ptr;
    }

    void addRedge(int from,int to,int dis)
    {
    Edge
    *ptr =&redge[ednum];
    ptr
    ->from = from;
    ptr
    ->to = to;
    ptr
    ->dis = dis;
    ptr
    ->next = re[from];
    re[from]
    =ptr;
    }

    struct dnode//dijkstra()优先队列中使用的节点
    {
    int v,len;//记录从出发点到节点v的长度
    booloperator<(const dnode &A)const
    {
    return A.len<len;
    }
    };

    void dijkstra(int s,int n)//计算各点到终点的距离
    {
    memset(visited,
    0,sizeof(visited));
    memset(dis,
    -1,sizeof(dis));
    priority_queue
    <dnode>Q;
    dnode cur,next;
    cur.len
    =0;
    cur.v
    = s;
    Q.push(cur);
    dis[s]
    =0;
    int vnum =0;//已访完的节点数
    while(!Q.empty())
    {
    cur
    = Q.top();

    Q.pop();
    if(visited[cur.v])continue;
    visited[cur.v]
    =1;
    vnum
    ++;
    if(vnum==n)return;
    for(Edge *ed = re[cur.v];ed!=NULL;ed=ed->next)
    {
    if(visited[ed->to]==0)
    {
    if(dis[ed->to]==-1||dis[ed->to]>cur.len+ed->dis)
    {
    next.len
    = cur.len+ed->dis;
    dis[ed
    ->to]=next.len;
    next.v
    = ed->to;
    Q.push(next);
    }
    }
    }

    }

    }

    struct anode//astar()优先队列中的节点
    {
    int to; //记录从出发点到当前节点的距离
    int len;
    booloperator<(const anode &A)const
    {
    if(dis[A.to]==-1)returnfalse;
    if(dis[to]==-1)returntrue;
    return A.len+dis[A.to]<len+dis[to];//估计函数的使用
    }
    };
    int aStar(int from,int to,int k)
    {
    memset(visited,
    0,sizeof(visited));

    priority_queue
    <anode>Q;
    anode cur,next;
    if(from==to)k++;//两点重合时按题意加1
    cur.len =0;
    cur.to
    = from;
    Q.push(cur);
    while(!Q.empty())
    {
    cur
    = Q.top();
    // printf("%d\n",cur.len);
    Q.pop();
    if(visited[cur.to]==k)return cur.len+dis[cur.to];
    if(visited[cur.to]>k)continue;
    visited[cur.to]
    ++;
    if(visited[to]==k)return cur.len;

    for(Edge *ptr = ed[cur.to];ptr;ptr=ptr->next)
    {
    next.len
    = cur.len+ptr->dis;
    next.to
    = ptr->to;
    Q.push(next);
    }

    }
    return-1;
    }
    int main()
    {
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
    init(n);
    ednum
    =0;
    while(m--)
    {
    int a,b,t;
    scanf(
    "%d%d%d",&a,&b,&t);
    a
    --;
    b
    --;
    addEdge(a,b,t);
    addRedge(b,a,t);
    ednum
    ++;
    }
    int s,t,k;
    scanf(
    "%d%d%d",&s,&t,&k);
    s
    --,t--;
    dijkstra(t,n);
    // for(int i=0;i<n;i++)
    // printf("%d\n",dis[i]);

    if(dis[s]==-1)printf("-1\n");
    else
    printf(
    "%d\n",aStar(s,t,k));
    }
    return0;
    }

     
  • 相关阅读:
    C#_简单实用的翻页
    C#注意事项及错误处理
    C# 委托和Lambda---基础
    C#_数据转换 实用方法
    C#图片处理---基础
    C#_使用SMTP发送邮件
    C#_生成HTML
    C#操作XML文档---基础
    百度地图 使用两条平行线表示路线
    Gradle version 2.10 is required. Current version is 2.8.
  • 原文地址:https://www.cnblogs.com/AndreMouche/p/1952358.html
Copyright © 2020-2023  润新知