#21#23神秘TLE,玄关
查看原帖
#21#23神秘TLE,玄关
927825
_OTR_楼主2025/8/31 16:17
蒟蒻梅石粒,思路是借鉴他人的(已标出)
#include<bits/stdc++.h>
using namespace std;
int const N = 2e5 + 5;
int n,m,s,t,cnt;
int head[N],nxt[N],to[N],dis[N];
bool vis[N];
inline int read(){
	int x = 0;char c = getchar();
	while(c < '0' || c > '9'){c = getchar();};
	while(c >= '0' && c <= '9'){x = ((x << 1) + (x << 3) + (c ^ 48));c = getchar();}
	return x;
}
inline void add(int a,int b){
	nxt[++cnt] = head[a];
	to[cnt] = b;
	head[a] = cnt;
}
void bfs(){
	queue<int> q;
	dis[t] = 0;//从终点开始,反向bfs 
	vis[t] = true;
	q.push(t);
	while(!q.empty()){
		int id = q.front();
		q.pop();
		int d = dis[id] + 1;
		for(int i = head[id]; i; i = nxt[i]){
			int v = to[i];
			if(dis[v] > d && !vis[v]){
				dis[v] = d;
				vis[v] = true;
				q.push(v);
			}
		}
	}
}
void solve(){
	n = read();m = read();s = read();t = read();
	cnt = 0;
	memset(vis,0,n + 3);
	memset(head,0,4 * n + 3);
	memset(dis,0x3f,4 * n + 3);
	for(int i = 1,u,v; i <= m; i++){
		u = read();v = read();
		if(u == v){
			continue;
		}
		add(u,v);
		add(v,u);
	}
	bfs();
	int ans = 1e9;
	for(int i = 0,um; i < n; i++){//考虑mex移动 
		um = dis[i];
		/*
		思路来源:LS_QYY 
		假设点i可以到达t,则dis[i]有效,那么需要先从s到达i 
		考虑直接从s开始全靠mex移动到i,会有以下可能的(问题/解决方法): 
		(1):其他可能到达i点的点,是会在其他遍历中计算的 
		(2):会不会漏掉在i之后又靠mex移动的情况? 
			如果有这种情况,设靠mex移动到mx点,说明"更优"的移动方案中包含mx点,  
			且节点(0 到 mx - 1)已被全部遍历,此时的行动次数至少为从s到0 
			再一直靠mex移动到mx点的次数,大于等于mx次, 
			那还不如直接在遍历到mx点时给答案加mx.当然,有特殊情况: 
			(1  当mx > s时,答案+mx 
			(2  当mx < s时,答案+(mx + 1) 
			(3  当mx = s时,答案直接就是dis[s] 
			除此之外,就是ans取最小值了 
		*/
		if(i > s){
			um += i;
		}
		else if(i < s){
			um += i + 1;
		}
		ans = min(ans,um);
	}
	printf("%d\n",ans);
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		solve();
	}
	return 0;
} 

QAQ

2025/8/31 16:17
加载中...