POJ 2449 spfa+基于A start algorithm 实现的k短路算法

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=100010;
struct Edge {
    int to,val,next;
} edge[maxn],edge2[maxn];
struct Node {
    int to,g,f;
    bool operator< (const Node &r) const {
        if(r.f==f)
            return r.g<g;
        return r.f<f;
    }
} ;
int n,m,s,t,k,cnt,cnt2;
int dis[1010],visit[1010],head[1010],head2[1010];
void init() {
    memset(head,-1,sizeof head);
    memset(head2,-1,sizeof head2);
    cnt=cnt2=1;
}
void addedge(int from,int to,int val) {
    edge[cnt].to=to;
    edge[cnt].val=val;
    edge[cnt].next=head[from];
    head[from]=cnt++;
}
void addedge2(int from,int to,int val) {
    edge2[cnt2].to=to;
    edge2[cnt2].val=val;
    edge2[cnt2].next=head2[from];
    head2[from]=cnt2++;
}
bool spfa(int s,int n,int head[],Edge edge[],int dist[]) {
    queue<int> q;
    int inq[1010];
    for(int i=0; i<=n; i++) {
        dis[i]=INF;
        inq[i]=0;
    }
    dis[s]=0;
    q.push(s);
    inq[s]++;
    while(!q.empty()) {
        int temp=q.front();
        q.pop();
        inq[temp]--;
        if(inq[temp]>n)
            return false;
        for(int i=head[temp]; i!=-1; i=edge[i].next) {
            if(dist[edge[i].to]>dist[temp]+edge[i].val) {
                dist[edge[i].to]=dist[temp]+edge[i].val;
                if(!inq[edge[i].to]) {
                    inq[edge[i].to]++;
                    q.push(edge[i].to);
                }
            }
        }
    }
    return true;
}
int A_star(int s,int t,int n,int k,int head[],Edge edge[],int dist[]) {
    Node e,nexte;
    int cnt=0;
    priority_queue<Node> q;
    if(s==t)
        k++;
    if(dis[s]==INF)
        return -1;
    e.to=s,e.g=0,e.f=e.g+dis[e.to];
    q.push(e);
    while(!q.empty()) {
        e=q.top(),q.pop();
        if(e.to==t)
            cnt++;
        if(cnt==k)
            return e.g;//g是确切值
        for(int i=head[e.to]; i!=-1; i=edge[i].next) {
            nexte.to=edge[i].to;
            nexte.g=e.g+edge[i].val;
            nexte.f=nexte.g+dis[nexte.to];
            q.push(nexte);
        }
    }
    return -1;
}
int main(void) {
#ifndef ONLINE_JUDGE
    freopen("E:\\input.txt","r",stdin);
#endif
    while(~scanf("%d%d",&n,&m)) {
        init();
        for(int i=1; i<=m; i++) {
            int t1,t2,t3;
            scanf("%d%d%d",&t1,&t2,&t3);
            addedge(t1,t2,t3);
            addedge2(t2,t1,t3);
        }
        scanf("%d%d%d",&s,&t,&k);
        spfa(t,n,head2,edge2,dis);
        printf("%d\n",A_star(s,t,n,k,head,edge,dis));
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值