当前位置: 首页 > article >正文

2025年3月GESP八级真题解析

第一题——上学

题目描述

C 城可以视为由 n n n 个结点与 m m m 条边组成的无向图。这些结点依次以 1 , 2 , … , n 1,2,…,n 1,2,,n 标号,边依次以 1 , 2 , … , m 1,2,…,m 1,2,,m 标号。第 i i i 条边( 1 ≤ i ≤ m 1≤i≤m 1im)连接编号为 u i u_i ui v i v_i vi 的结点,长度为 l i l_i li 米。

小 A 的学校坐落在 C 城中编号为 s s s 的结点。小 A 的同学们共有 q q q 位,他们想在保证不迟到的前提下,每天尽可能晚地出门上学。但同学们并不会计算从家需要多久才能到学校,于是找到了聪明的小 A。第 i i i 位同学( 1 ≤ i ≤ q 1≤i≤q 1iq)告诉小 A,他的家位于编号为 h i h_i hi 的结点,并且他每秒能行走 1 1 1 米。请你帮小 A 计算,每位同学从家出发需要多少秒才能到达学校呢?

输入格式

第一行,四个正整数 n , m , s , q n,m,s,q n,m,s,q,分别表示 C 城的结点数与边数,学校所在的结点编号,以及小 A 同学们的数量。

接下来 m m m 行,每行三个正整数 u i , v i , l i u_i,v_i,l_i ui,vi,li,表示 C 城中的一条无向边。

接下来 q q q 行,每行一个正整数 h i h_i hi,表示一位同学的情况。

输出格式

q q q 行,对于每位同学,输出一个整数,表示从家出发到学校的最短时间。

样例

输入样例 1

5 5 3 3
1 2 3
2 3 2
3 4 1
4 5 3
1 4 2
5
1
4

输出样例 1

4
3
1

数据范围

对于 20 % 20\% 20% 的测试点,保证 q = 1 q=1 q=1

对于另外 20 % 20\% 20% 的测试点,保证 1 ≤ n ≤ 500 , 1 ≤ m ≤ 500 1≤n≤500,1≤m≤500 1n5001m500

对于所有测试点,保证 1 ≤ n ≤ 2 × 1 0 5 , 1 ≤ m ≤ 2 × 1 0 5 , 1 ≤ q ≤ 2 × 1 0 5 1≤n≤2×10^5,1≤m≤2×10^5,1≤q≤2×10^5 1n2×1051m2×1051q2×105 1 ≤ u i , v i , s , h i ≤ n , 1 ≤ l i ≤ 1 0 6 1≤u_i,v_i,s,h_i≤n,1≤l_i≤10^6 1ui,vi,s,hin1li106。保证给定的图联通。

分析

这道题其实非常简单,是一道裸的最短路问题,我们只需要从终点出发反着跑就可以了,非常的简单。

#include<bits/stdc++.h>
using namespace std;
const int INF=2e5+10;

struct Node{
	long long v,num;
	bool operator <(const Node &a)const{
		return num>a.num;
	}
};

vector<Node> mp[INF];
long long dis[INF],used[INF];
priority_queue<Node> q;

void dijkstra(int x){
	dis[x]=0,q.push({x,0});
	while (!q.empty()){
		long long u=q.top().v;q.pop();
		if (used[u]==1)continue;
		used[u]=1; 
		int len=mp[u].size();
		for (int i=0;i<len;i++){
			long long v=mp[u][i].v,w=mp[u][i].num;
			if (dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				q.push({v,dis[v]});
			}
		}
	}
}

int main(){
	int n,m,s,q;
	cin>>n>>m>>s>>q;
	for (int i=1;i<=n;i++){
		dis[i]=1e18;
	}
	for (int i=1;i<=m;i++){
		long long u,v,l;
		cin>>u>>v>>l;
		mp[u].push_back({v,l});
		mp[v].push_back({u,l});
	}
	dijkstra(s);
	for (int i=1;i<=q;i++){
		int t;
		cin>>t;
		cout<<dis[t]<<endl;
	}
	return 0;
}

广告
最短路算法——CSDN
最短路算法——博客园

第二题——割裂

题面描述

小杨有一棵包含 n n n 个节点的树,其中节点的编号从 1 1 1 n n n

小杨设置了 a a a 个好点对< u 1 u_1 u1, v 1 v_1 v1>,< u 2 u_2 u2, v 2 v_2 v2>,…,< u a u_a ua, v a v_a va>和 1 个坏点对 < b u b_u bu, b v b_v bv>。一个节点能够被删除,当且仅当:

删除该节点后对于所有的 i ( 1 ≤ i ≤ a ) i(1≤i≤a) i(1ia),好点对 u i u_i ui v i v_i vi 仍然连通;
删除该节点后坏点对 b u b_u bu b v b_v bv 不连通。
如果点对中的任意一个节点被删除,其视为不连通。

小杨想知道,有多少个节点能够被删除。

输入格式

第一行包含两个正整数 n , a n,a n,a,含义如题面所示。

之后 n − 1 n−1 n1 行,每行包含两个正整数 x i , y i x_i,y_i xi,yi,代表存在一条连接节点 x i x_i xi y i y_i yi 的边。

之后 a a a 行,每行包含两个正整数 u i , v i u_i,v_i ui,vi,代表一个好点对 < u i , v i u_i,v_i ui,vi>。

最后一行包含两个正整数 b u , b v b_u,b_v bu,bv,代表坏点对 < b u , b v b_u,b_v bu,bv>。

输出格式

输出一个正整数,代表能够删除的节点个数。

样例

输入样例

6 2
1 3
1 5
3 6
3 2
5 4
5 4
5 3
2 6

输出样例

2

数据范围

对于全部数据,保证有 1 ≤ n ≤ 1 0 6 , 0 ≤ a ≤ 1 0 5 , u i ≠ v i , b u ≠ b v 1≤n≤10^6,0≤a≤10^5,ui≠vi,bu≠bv 1n106,0a105,ui=vi,bu=bv

分析

这道题其实还有点思维含量,根据题目,我们要知道那些点是能删的,那些点是不能删的,基于此,我们就要维护出来每个点被那些点所经过了,或者说被经过了几次,如果说一个点没有被任何的好点经过,并且被坏点经过了,那么就说明这个点是可以被删除的,我这里说的被好点经过指的是两个好点之间的路径哈,不要搞错了。

如果说思路是这样的话,我们是不是就可以很显然想到一个做法,树上差分?而且这个是一个非常简答的点差分,所以说没有任何的难度好吧。

#include<bits/stdc++.h>
using namespace std;
const int INF=1e6+10;

vector<int> mp[INF];
int dp[INF][30],deep[INF],p[INF],d[INF];

void prepare(int x,int fa){
	for (int i=1;(1<<i)<=deep[x]-1;i++){
		dp[x][i]=dp[dp[x][i-1]][i-1];
	}
	int len=mp[x].size();
	for (int i=0;i<len;i++){
		if (mp[x][i]==fa)continue;
		int t=mp[x][i];
		dp[t][0]=x,deep[t]=deep[x]+1;
		prepare(t,x);
	}
}
int getroot(int x,int y){
	if (deep[x]<deep[y])swap(x,y);
	int index=__lg(deep[x]-deep[y]);
	for (int i=index;i>=0;i--){
		if (deep[dp[x][i]]>=deep[y])x=dp[x][i];
		if (deep[x]==deep[y])break;
	}
	if (x==y)return x;
	for (int i=20;i>=0;i--){
		if (dp[x][i]!=dp[y][i])x=dp[x][i],y=dp[y][i];
	}
	return dp[x][0];
}

void get_p(int x,int fa){
	int len=mp[x].size();
	for (int i=0;i<len;i++){
		if (mp[x][i]==fa)continue;
		int t=mp[x][i];
		get_p(t,x);
		p[x]+=p[t];
	}
}

void get_d(int x,int fa){
	int len=mp[x].size();
	for (int i=0;i<len;i++){
		if (mp[x][i]==fa)continue;
		int t=mp[x][i];
		get_d(t,x);
		d[x]+=d[t];
	}
}
int main(){
	int n,a;
	cin>>n>>a;
	for (int i=1;i<n;i++){
		int u,v;
		cin>>u>>v;
		mp[u].push_back(v);
		mp[v].push_back(u);
	}
	deep[1]=1;
	prepare(1,-1);
	for (int i=1;i<=a;i++){
		int u,v;
		cin>>u>>v;
		int root=getroot(u,v);
		p[u]++,p[v]++,p[root]--,p[dp[root][0]]--;
	}
	get_p(1,-1);
	int b1,b2;
	cin>>b1>>b2;
	int root=getroot(b1,b2);
	d[b1]++,d[b2]++,d[root]--,d[dp[root][0]]--;
	get_d(1,-1);
	int cnt=0;
	for (int i=1;i<=n;i++){
		if (d[i]&&!p[i])cnt++;
	}
	cout<<cnt;
	return 0;
}

总结

这次的八级题不算难,只不过前面的选择题和判断题CCF出错了,所以说耽误了一点时间,对于基础比较好的人来说,这套八级的题大概是可以在1个半小时内做完的(像我这么一个蒟蒻,都只花了差不多1个小时)


http://www.kler.cn/a/596557.html

相关文章:

  • 收数据花式画图plt实战
  • 【CXX-Qt】2.3 类型
  • 网站蜜罐部署与攻击追踪方案
  • 【指针(2)-- 使用指针的技巧】
  • 人工智能在智能交通中的应用:以L4级无人电动物流拖车为例
  • 解析DeepSeek的技术内核:混合专家架构如何重塑AI效能
  • 【第16章】亿级电商平台订单系统-部署架构设计
  • 蓝桥杯备考:模拟题之神奇的幻方
  • 2025年渗透测试面试题总结- shopee-安全工程师(题目+回答)
  • asp.net core mvc模块化开发
  • 网络知识编-数据链路层(以太网 局域网通信 ARP协议 ARP 欺骗 DDos 攻击)
  • Linux系统管理与编程07:任务驱动综合应用
  • 蓝牙AOA定位技术:开启车辆精准定位的智能新时代
  • MySQL数据库精研之旅第二期:库操作的深度探索
  • python:AI+ music21 构建 LSTM 模型生成爵士风格音乐
  • 【Java篇】静动交融,内外有别:从静态方法到内部类的深度解析
  • 单表达式倒计时工具:datetime的极度优雅(DeepSeek)
  • C++异常处理完全指南:从原理到实战
  • vue3配置代理实现axios请求本地接口返回PG库数据【前后端实操】
  • 红宝书第八讲:箭头函数与高阶函数:厨房工具与智能菜谱的对比