hdu.6705.path(k短路径)

hdu.6705.path(k短路径)

思路:优先队列 + + +优化。

考虑对每个节点的出边排序,然后将每个结点的最小出边加入到队列。

接着考虑两种情况:

对于当前最短路径最后的一条边 u → v u\rightarrow v uv,路径权值和为 w w w

1.选择 u u u的下一条出边 u → v 1 , u\rightarrow v_1, uv1,路径权值和为 w + w ( u , v 1 ) − w ( u , v ) w+w(u,v_1)-w(u,v) w+w(u,v1)w(u,v)

2.延申到 v v v的最短出边 v → x v\rightarrow x vx, 路径权值和为 x , w + w ( v , x ) x,w+w(v,x) x,w+w(v,x)

#include
using namespace std;
typedef long long ll;
const int N=5e4+100,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair
#define fi first
#define se second
#define pb push_back
#define il inline
ll n,m,t;
vector<PII>g[N];
ll Q[N],mx;
ll a[N];
struct node{
     
	ll u,v,w,id;
	bool operator<(const node&no)const{
     
		return w>no.w;
	}
};
int main(){
     
	ll T;
	scanf("%lld",&T);
	while(T--){
     
	scanf("%lld%lld%lld",&n,&m,&t);
	mx=0;
	for(int i=1;i<=n;i++) g[i].clear();
	for(int i=1;i<=m;i++){
     
		ll u,v,w;
		scanf("%lld%lld%lld",&u,&v,&w);
		g[u].pb({
     w,v});
	}
	for(int i=1;i<=n;i++){
     
		sort(g[i].begin(),g[i].end());
	}
	for(int i=1;i<=t;i++){
     
		scanf("%lld",&Q[i]);
		 mx=max(mx,Q[i]);
	} 
	priority_queue<node>q;
	for(int i=1;i<=n;i++){
     
		if(!g[i].empty()){
     
		q.push({
     i,g[i][0].se,g[i][0].fi,0});
		//printf("(%d %d %d %d)\n",i,g[i][0].se,g[i][0].fi,0);
		}	
	}
	ll cnt=0;
	while(cnt<mx&&!q.empty()){
     
		ll u=q.top().u,v=q.top().v,w=q.top().w;
		ll id=q.top().id;q.pop();
		id++,a[++cnt]=w;
		if(id<g[u].size()){
     
			q.push({
     u,g[u][id].se,g[u][id].fi+w-g[u][id-1].fi,id});
		} 
		if(g[v].size()) q.push({
     v,g[v][0].se,g[v][0].fi+w,0});
	} 
	for(int i=1;i<=t;i++) printf("%lld\n",a[Q[i]]);
	}
	return 0;
}

你可能感兴趣的:(最短路)