(CCPC) 网络赛 1004 path (思维)

5 篇文章 0 订阅

传送门

题意:给你有向图,每次查询第k长的路径,而且这里面环状路径可以无限走。

解:被次大最短路,或者第k大最短路的思想所限制了,题解的思路就很简单了,被按在地上摩擦,就是用优先队列按照距离从小到大排序,把一个点取出时,可能加进去的答案就是当前这个节点连出去的边最短的那一条(点出去的边也需要排序),或者上一个节点还可以延展出去的路径。在将查询排序一下,就可以了。

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn=5e4+5;
struct node {
	ll to,w;
	bool operator < (const node &p) const {
		return w<p.w;
	}
};
vector<node> mp[maxn];
struct P {
	ll pdist,pre,id,ndist,np;
	bool operator < (const P &p) const {
		return ndist>p.ndist;
	}
};
priority_queue<P> q;
struct PP {
	int id,k;
	bool operator < (const PP &p) const {
		return k<p.k;
	}
} qu[maxn];

int T,n,m,qnum,ans[maxn];
int main() {
	scanf("%d",&T);
	while(T--) {
		scanf("%d%d%d",&n,&m,&qnum);
		for(int i=1; i<=n; ++i) mp[i].clear();
		while(!q.empty()) q.pop();

		ll u,v,w,k;
		for(int i=1; i<=m; ++i) {
			scanf("%lld%lld%lld",&u,&v,&w);
			mp[u].push_back(node {v,w});
			q.push(P {0,-1,0,w,v});
		}
		for(int i=1; i<=n; ++i) {
			sort(mp[i].begin(),mp[i].end());
		}
		for(int i=1; i<=qnum; ++i) {
			scanf("%lld",&k);
			qu[i]=PP {i,k};
		}
		sort(qu+1,qu+qnum+1);

		ll pdist,pre,id,ndist,np,cnt=1,qid=1;
		P top;
		while(1) {
			top=q.top(),q.pop();
			while(cnt == qu[qid].k && qid<=qnum) {
				ans[qu[qid].id]=top.ndist;
				qid++;
			}
			if(qid==qnum+1) break;
			cnt++,k--;
			pdist=top.pdist,pre=top.pre;
			id=top.id,ndist=top.ndist,np=top.np;
//			cout<<pdist<<" "<<pre<<" "<<id<<" "<<ndist<<" "<<np<<endl;
			if(pre!=-1 && id<(int)mp[pre].size()) {
				q.push(P {pdist,pre,id+1,pdist+mp[pre][id].w,mp[pre][id].to});
			}
			if((int)mp[np].size()) q.push(P {ndist,np,1,ndist+mp[np][0].w,mp[np][0].to});
		}
		for(int i=1; i<=qnum; ++i) printf("%lld\n",ans[i]);

	}
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值