hdu6181 Two Paths

一道A*算法求第k短路的模板题,但是!我有话要说。

可能因为学校老师比较水,我们讲迪杰斯特拉算法的时候老师讲了个n^2算法实现的,教科书上也他妈n^2,我也没细想

后来比赛的时候我自己优化了,结果一百度发现直接优先级队列,elogn。。。。。伤心,错过一道水题。

自己做了个模板,以后直接用。对了,A*算法确实有复杂的用法,但是我们这里只要利用他求第k短就行了。

至于估值函数 F=G+H 这里求H用了迪杰斯特拉算法。

#include<iostream>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int T,n,m,a,b,w;
ll inf=1e18;
typedef struct node { //dij and mp
	int at;
	ll len;
	bool operator < (const node &te) const { 
		return len>te.len;
	}
}node;
typedef struct _node { //Astar
	int at;
	ll len;
	ll tot;
	bool operator < (const _node &te) const { 
		return tot>te.tot;
	}
}_node;
vector<node> mp[100005];
ll dis[100005];

ll dij(int go) {
	priority_queue<node> q;
	for(int i=1;i<=n;i++) {
		dis[i]=inf;
	}
	dis[go]=0;
	q.push(node{go,0});
	while(!q.empty()) {
		node e=q.top(); q.pop();//这里加跳出判断可以求出最短路,也就是单纯的dij 
		for(int i=0;i<mp[e.at].size();i++) {
			node xe=mp[e.at][i];
			if(e.len+xe.len<dis[xe.at]) {
				dis[xe.at]=e.len+xe.len;
				q.push(node{xe.at,e.len+xe.len});
			}
		}
	}
	return 0;//返回最短路径,这个题目不需要 
}

ll Astar(int Start,int End,int Knum) {
    priority_queue<_node> q;
    q.push(_node{Start,0,dis[Start]});
    while(!q.empty()) {
    	_node e=q.top(); q.pop();
    	if(e.at==End) {
    		Knum--;
    		if(Knum==0) 
    		    return e.tot;
		}
    	for(int i=0;i<mp[e.at].size();i++) {
    		node xe=mp[e.at][i];
    		q.push(_node{xe.at,e.len+xe.len,e.len+xe.len+dis[xe.at]});
		}
	}
}

int main() {
	scanf("%d",&T);
	while(T--) {
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++) {
			mp[i].clear();
		}
		for(int i=1;i<=m;i++) {
			scanf("%d%d%d",&a,&b,&w);
			mp[a].push_back(node{b,w});
			mp[b].push_back(node{a,w});
		}
		
		int Start=1,End=n,Knum=2;//A*求第Knum段路 
		ll ans1=dij(n);
		ll ansKnum=Astar(Start,End,Knum);
		printf("%lld\n",ansKnum);
	}
	return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值