【模板】 $\text{K}$ 短路

Tags

搜索、\(\text{A*}\)很酷很炫的算法


  • 定义二元组\(\text{DIS(X,Now)}\)表示到达\(\text{X}\)点,路程是\(\text{Now}\)
  • 反向\(\text{SPFA/Dijkstra}\)作为每个点的估价函数;
  • 从队首取出\(\text{DIS}\),扩展状态;
  • 每当获得一个\(\text{DIS}​\)就加入到\(\text{priority_queue}​\)里面去;

Code:

#include <cstdio>
#include <cstring>
#include <queue>
#define re register
#define GC getchar()
#define Clean(X,K) memset(X,K,sizeof(X))
int Qread () {
	int X = 0 ;	char C = GC ;
	while (C > '9' || C < '0') C = GC ;
	while (C >='0' && C <='9') {
		X = X * 10 + C - '0' ;
		C = GC ;
	}
	return X ;
}
const int Maxn = 5005 , Maxm = 400005 , INF = 20021020 << 2;
int N , M , Head[Maxn] , En = 0 , Vis[Maxn] ;
double Ek , Mdis[Maxn];
struct DIS {
	int X ;
	double Now ;
};
bool operator < (const DIS &A , const DIS &B) {
	return A.Now + Mdis[A.X ] > B.Now + Mdis[B.X ] ;
}
std :: priority_queue <DIS> Q ;
struct Edge {
	int From_Point , Goto_Point , Next_Edge ;
	double Lenth_of_Edge ;
};
Edge E[Maxm] ;
void Adg (int X , int Y , double L) {
	E[++En].From_Point =X ;
	E[En].Goto_Point = Y ;
	E[En].Next_Edge = Head[X] ;
	E[En].Lenth_of_Edge = L ;
	Head[X] = En ;
}
void SPFA () {
	std :: queue <int> Q ;
	for (re int i = 1 ; i <= N; ++ i) Mdis[i] = INF ;
	Clean (Vis , 0) , Mdis[N] = 0 ;
	Q.push(N) ;
	while (!Q.empty()) {
		int Now = Q.front() ;
		Q.pop() ;
		Vis[Now] = 0 ;
		for (re int i = Head[Now] ; i; i = E[i].Next_Edge ) {
			double Dis = Mdis[Now] + E[i].Lenth_of_Edge ;
			if (Mdis[E[i].Goto_Point ] > Dis) {
				Mdis[E[i].Goto_Point ] = Dis ;
				if (!Vis[E[i].Goto_Point ]) {
					Vis[E[i].Goto_Point ] = 1 ;
					Q.push(E[i].Goto_Point ) ;
				}
			}
		}
	}
}
DIS Mp (int X , double Now) {
	DIS Ans ;
	Ans.X = X , Ans.Now = Now ;
	return Ans ;
}
int main () {
//	freopen ("P2483.in" , "r" , stdin) ;
	N = Qread () , M = Qread () ;
	scanf ("%lf" , &Ek) ;
	Clean (Head , 0) , En = 0 ;
	for (re int i = 1 ; i <= M; ++ i) {
		double L ;
		int X = Qread () , Y = Qread () ;
		scanf ("%lf" , &L) ;
		Adg (Y , X , L) ;
	}
	SPFA () ;
	Clean(Head , 0 ) , En = 0 , M <<= 1 ;
	for (re int i = 1 ; i <= M ; ++ i) Adg (E[i].Goto_Point , E[i].From_Point , E[i].Lenth_of_Edge ) ;
	M >>= 1 ;
	Q.push(Mp(1 , 0)) ;
	int Ans = 0 ;
	while (!Q.empty()) {
		DIS Now = Q.top() ;
		Q.pop() ;
		if (Now.X == N) {
			Ek -= Now.Now ;
			if (Ek < 0) break ;
			++ Ans ;
			continue ;
		}
		for (re int i = Head[Now.X ] ; i; i = E[i].Next_Edge ) Q.push(Mp(E[i].Goto_Point , Now.Now + E[i].Lenth_of_Edge )) ;
	}
	printf ("%d\n" , Ans) ;
	fclose (stdin) , fclose (stdout) ;
	return 0 ;
}

Thanks!

posted @ 2019-03-17 10:31  Betulaceae  阅读(189)  评论(0编辑  收藏  举报