PTA xt的考研路 往返 最短路

该文讲述了xt同学为了挑战自我,决定考研并尝试填补学院无北大研究生的空白。他通过三点一线的学习模式努力备考。文章提出了一个图论问题,寻找从寝室、食堂到图书馆的最小边权和子图,通过跑最短路算法解决。如果找不到符合条件的子图,则输出特定信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

xt是我院19级专业第一,但他认为保研并不能展示他全部的实力,所以他在22年初试一结束就加入了23考研的队伍中,并且他为了填补我院近些年来无北大研究生的空白,毅然决然决定扛起19级的大旗,在学校百年华诞之际献上他最诚挚的礼物。

xt每天都游走在寝室,食堂和图书馆,三点一线,即便是在疫情局势蔓延的形势下,凌晨三点半刚做完核酸,他六点半还是照常起来卷。现在他太忙了,好像在提前准备复试了,想让你帮个小忙,xt会给出学校的地图(有向图),并且给出寝室,食堂和图书馆的编号(编号从0开始),希望你从该图中找出一个子图,要使得在这个子图中,寝室能够到达图书馆,食堂也能到达图书馆,同时希望在这个子图中的所有边的边权之和最小。如果你找不到任何一个子图符合要求的话(),输出“xt,我好没本领!”,因为你找不到并不代表xt找不到

子图的定义:

 从原图中删去一些点或删去一些线或既删去一些点又删去一些线,剩下的部分(当然必须仍然是图)。允许两种极端情况:什么都不删;删去所有点和所有线。

 

输入格式:

第一行输入点的个数 n,3 <= n <= 105,边的个数 m,0 <= m <= 2∗105

第二行给出寝室的编号id1,食堂的编号id2,图书馆的编号id3,题目保证三个编号两两不同。

随后 m 行按照以下形式描述边,表示有一条有向边,起点是from,终点是to,权值是w

from to w

 0 <= from, to <= n - 1,from != to,1 <= w <= 10^9

输出格式1:

如果子图存在则输出最小边权和,如果不存在输出“xt,我好没本领!”

输入样例1:

6 9
0 1 5
0 2 2 
0 5 6 
1 0 3 
1 4 5 
2 1 1 
2 3 3 
2 3 4 
3 4 2 
4 5 1

输出样例1:

9

解释:

上图为输入的图。

蓝色边为最优子图之一。

注意,直接选择0 1 5三点构成的子图也能得到最优解,但无法在满足所有限制的前提下,得到更优解。

输入样例2:

3 2
0 1 2
0 1 1
2 1 1

输出样例2:

xt,我好没本领!

解释:

上图为输入的图。

可以看到,不存在从节点 1 到节点 2 的路径,所以不存在任何子图满足所有限制。

 思路:

       1.跑以寝室,食堂为起点的最短路,存入d_1, d_2 。

       2.跑以图书馆为起点的反向最短路,存入d_3。

       3.便历从0->n所有点,以d_1[i] + d_2[i] + d_3[i]  为所有点到这个点的路径长度,

一直取其最小(ans=min(d_1[i] + d_2[i] + d_3[i],ans)

如果未改变,就按题目要求输出,改变了就输出ans;

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pli pair<ll,int>
ll n , m , k , idx , cnt;
const ll inf = 0x3f3f3f3f3f3f/3;
const int l = 200005;
const int r = 100005;
int ne_12[l] , e_12[l] , h_12[l] ;
int ne_3 [l] , e_3 [l] , h_3 [l] ;
ll d_1[r] , d_2[r] , d_3[r] , dist_12[r] , w_12[l] , w_3 [l];
bool st[r];
void add(int a,int b,int c){
	ne_12[idx] = h_12[a];
	e_12[idx] = b;
	w_12[idx] = c;
	h_12[a] = idx ++;
/*QWQ QWQ QWQ QWQ QWQ QWQ QWQ QWQ QWQ QWQ QWQ QWQ QWQ QWQ QWQ QWQ QWQ QWQ QWQ QWQ QWQ QWQ*/
	ne_3[cnt] = h_3[b];
	e_3[cnt] = a;
	w_3[cnt] = c;
	h_3[b] = cnt ++;
}
void bfs_12(int x){
	memset(st , 0 ,sizeof st);
	for(int i = 0 ; i < n ; i ++)dist_12[i] = inf;
	priority_queue<pli,vector<pli>,greater<pli> >q;
	q.push({0,x}); dist_12[x] = 0;
	while(!q.empty()){
		int t = q.top().second;
		q.pop();
		if(st[t])continue;
		st[t] = 1;
		for(int i = h_12[t] ; i != -1 ; i = ne_12[i]){
			int to = e_12[i];
			if(dist_12[to] <= dist_12[t] + w_12[i])continue;
			dist_12[to] = dist_12[t] + w_12[i];
			q.push({dist_12[to],to});
		}
	}
}
void bfs_3(int x){
	memset(st , 0 , sizeof st);
	for(int i = 0 ; i < n ; i ++)d_3[i] = inf;
	priority_queue<pli,vector<pli>,greater<pli> >q;
	q.push({0,x});d_3[x] = 0;
	while(!q.empty()){
		int t = q.top().second;
		q.pop();
		if(st[t])continue;
		st[t] = 1;
		for(int i = h_3[t] ; i != -1 ; i = ne_3[i]){
			int to = e_3[i];
			if(d_3[to] <= d_3[t] + w_3[i])continue;
			d_3[to] = d_3[t] + w_3[i];
			q.push({d_3[to],to});
		}
	}
}
int main(){
	int qs , st , tsg;
	cin >> n >> m;
	cin >> qs >> st >> tsg;
	idx = cnt = 0;
	memset(h_3 , -1 , sizeof h_3);
	memset(h_12 , -1 , sizeof h_12);
	while(m --){
		int a , b , c;
		cin >> a >> b >> c;
		add(a,b,c);
	}
	bfs_12(st);for(int i = 0 ; i < n ; i ++)d_1[i] = dist_12[i];
	bfs_12(qs);for(int i = 0 ; i < n ; i ++)d_2[i] = dist_12[i];
	bfs_3(tsg);
	ll ans = inf;
	for(int i = 0 ; i < n ; i ++){
		if(d_1[i] >= inf || d_2[i] >= inf || d_3[i] >= inf
		|| d_1[i] < 0 || d_2[i] < 0 || d_3[i] < 0)continue;
		ans = min(ans,d_1[i]+d_2[i]+d_3[i]); 
	}
	if(ans >= inf)cout << "xt,我好没本领!\n";
	else cout << ans << endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值