POJ 2449 Remmarguts' Date (A* 第k短路)

32 篇文章 0 订阅
7 篇文章 0 订阅

题目链接

给出n个点,m条边的有向图,问s到t的第k短路长度。

使用A*进行计算,每次不判重,把每一个点的相邻的所有状态加入到扩展集合中,判断t出队的次数为k就是k短路。 这里的 A *的H函数我们用单源最短路径计算从t到每个点的最短距离,因为是有向图计算的时候把图反向一下。

注意:当s==t的时候,k需要加以1。

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
#define cl(a,b) memset(a,b,sizeof(a))
#define fastIO ios::sync_with_stdio(false);cin.tie(0);
#define LL long long
#define pb push_back
#define gcd __gcd


#define For(i,j,k) for(int i=(j);i<=k;i++)
#define lowbit(i) (i&(-i))
#define _(x) printf("%d\n",x)

typedef vector<LL> vec;
typedef pair<int,int> PI;
const double EPS = 1e-8;
const int maxn = 2e5;
const int inf  = 1 << 28;

vector<pair<int,int> > G[maxn];
vector<pair<int,int> > rG[maxn];
int n,m;
int s,t,k;

int H[maxn];
bool inq[maxn];
void spfa(){
    queue<int> q;
    cl(inq,false);
    fill(H,H+n+100,inf);
    q.push(t);
    H[t] = 0;
    inq[t] = true;
    while(!q.empty()){
        int u = q.front();q.pop();
        for(int i=0;i<rG[u].size();i++){
            int v = rG[u][i].first;
            int w = rG[u][i].second;
            if(H[v] > H[u] + w){
                H[v] = H[u] + w;
                if(!inq[v]){
                    inq[v] = true;
                    q.push(v);
                }
            }
        }
        inq[u] = false;
    }
}

struct node{
    int x;
    int F,G;//G函数 实际的步数
    bool operator<(const node&rhs) const{
        return F > rhs.F || F == rhs.F && G > rhs.G;
    }

}start,last,cur;

int bfs(){
    start = (node){s,0+H[s],0};
    priority_queue<node> q;
    q.push(start);
    while(!q.empty()){
        last = q.top();q.pop();
        if(last.x == t && --k == 0){
            return last.G;
        }
        for(int i=0;i<G[last.x].size();i++){
            int v = G[last.x][i].first;
            int w = G[last.x][i].second;
            //printf("v = %d, w = %d\n",v,w);
            cur.x = v;
            cur.G = last.G + w;
            cur.F = cur.G + H[v];
            q.push(cur);
        }
    }
    return -1;
}


int main(){
    while(~scanf("%d%d",&n,&m)){
        for(int i=0;i<=n;i++){
            G[i].clear();
            rG[i].clear();
        }
        for(int i=0;i<m;i++){
            int x,y,w;
            scanf("%d%d%d",&x,&y,&w);
            G[x].pb(make_pair(y,w));
            rG[y].pb(make_pair(x,w));
        }
        scanf("%d%d%d",&s,&t,&k);if(s==t)k++;

        spfa();

        int ans = bfs();
        printf("%d\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值