풀이

[백준] 20870 - Teleportgång (c++)

땅왕 2024. 9. 24. 09:38

https://www.acmicpc.net/problem/20870

감상

역시나 파라메트릭이라 어려웠다. 그래도 점점 파라메트릭의 재미를 알아가고 있는 것 같다.

 

문제 요약

무방향 그래프와 시작점,끝점이 주어진다. 1초 동안 이어진 정점으로 이동하거나 랜덤 정점으로 이동할 수 있을 때 끝점까지 이동하는 최소 기대값을 구해라.

 

풀이 (NlogN)

  • Parametric Search
  • BFS

BFS로 끝점 기준의 거리(모든 정점에서 끝점까지 거리) 를 저장해 두고 랜덤 노드에서 시작점에 도달하는 최소 기대값을 기준으로 파라메트릭을 돌릴 수 있습니다. 랜덤 노드에서 시작점에 도달하는 최소 기대값을 x라고 할 때, 특정 노드에서 끝 점으로 이동하는 기대값은 min(거리,x+1(특정노드>랜덤노드가 1, 랜덤노드>끝노드가 x))이 되기 때문에 이분 탐색문 안에서 모든 정점을 순회하며 끝점으로 이동하는 기대값의 sum을 구하고 sum<x*n이면 작은 쪽으로 아니면 큰 쪽으로 범위를 좁힐 수 있습니다. x를 기대값(평균)으로 정의 했기 때문에 sum<x*n이라면 평균값이 더 작다는 의미가 되기 때문입니다. 소수를 이분 탐색하는 건 탐색 횟수를 충분한 값으로 고정해두고 돌리는 방법을 사용하였습니다.

 

#include <bits/stdc++.h>
using namespace std;
#define ll long long

int main() {
	cin.tie(0)->sync_with_stdio(0);
	int n,m,s,t;cin>>n>>m>>s>>t;
	vector<int> adj[n+1];
	for(int i=0,u,v;i<m;i++)
		cin>>u>>v,adj[u].push_back(v),adj[v].push_back(u);
	
	int d[n+1];fill(d,d+n+1,1e9);
	queue<int> q;
	d[t]=0; q.push(t);
	while(q.size()) {
		int u=q.front();q.pop();
		for(int v:adj[u]) if(d[v]==1e9)
			d[v]=d[u]+1,q.push(v);
	}

	double l=0,r=1e9;
	for(int i=0;i<100;i++) {
		double mid=(l+r)/2;
		double x=0;
		for(int i=1;i<=n;i++) {
			if(d[i]>mid+1) x+=mid+1;
			else x+=d[i];
		}
		if(x<mid*n)
			r=mid;
		else
			l=mid;
	}
	if(d[s]<l+1)cout<<d[s];
	else cout<<fixed<<setprecision(2)<<l+1;
}