제출 #1325367

#제출 시각아이디문제언어결과실행 시간메모리
1325367SonicMLTorrent (COI16_torrent)C++20
100 / 100
322 ms23916 KiB
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int const INF = 1e9+7;

int const NMAX = 3e5;

int n;

vector <int> g[1 + NMAX];

int dist;
vector <int> path;

bool buildPath(int node, int parent, int target) {
  if(node == target) {
    path.push_back(node);
    return true;
  }
  for(int i = 0;i < g[node].size();i++) {
    int to = g[node][i];
    if(to != parent) {
      if(buildPath(to, node, target)) {
        path.push_back(node);
        return true;
      }
    }
  }
  return false;
}

int dp[1 + NMAX];

void computeDp(int node, int parent, int border1, int border2) {
  dp[node] = 0; 
  //cerr << "  " << node << "/\n";
  for(int i = 0;i < g[node].size();i++) {
    int to = g[node][i];
    if(to != parent && !((node == border1 && to == border2) || (node == border2 && to == border1))) {
      computeDp(to, node, border1, border2);  
    }
  }
  vector <int> aux;
  for(int i = 0;i < g[node].size();i++) {
    int to = g[node][i];
    if(to != parent && !((node == border1 && to == border2) || (node == border2 && to == border1))) {
      aux.push_back(dp[to]);
    }
  }
  if(aux.size() > 0) {
    sort(aux.begin(), aux.end());
    int add = aux.size();
    for(int i = 0;i < aux.size();i++) {
      dp[node] = max(dp[node], aux[i]+add);
      add--;
    }
  }
  //cerr << "  " << node << " : " << dp[node] << "\\\n";
}

int solve(int sourceA, int sourceB, int border1, int border2) {
  int solA, solB;
  computeDp(sourceA, sourceA, border1, border2);
  solA = dp[sourceA];
  computeDp(sourceB, sourceB, border1, border2);
  solB = dp[sourceB];
  return max(solA, solB);
}

int auxSolve(int sourceA, int sourceB, int border1, int border2) {
  int solA, solB;
  computeDp(sourceA, sourceA, border1, border2);
  solA = dp[sourceA];
  computeDp(sourceB, sourceB, border1, border2);
  solB = dp[sourceB];
  return (solA - solB);
}

int cautbinBorder(int from, int to, int sourceA, int sourceB) {
  if(from >= to) {
    return from;
  }else {
    int mid = (from + to) / 2;
    int border1 = path[mid-1], border2 = path[mid]; 
    if(auxSolve(sourceA, sourceB, border1, border2) > 0) {
      return cautbinBorder(from, mid, sourceA, sourceB);
    }else {
      return cautbinBorder(mid+1, to, sourceA, sourceB);
    }
  }
}

int main() {

  ios_base::sync_with_stdio(false);
  cin.tie(0);
  int sourceA, sourceB;
  cin >> n >> sourceA >> sourceB;
  for(int i = 1;i < n;i++) {
    int a, b;
    cin >> a >> b;
    g[a].push_back(b);
    g[b].push_back(a);
  }
  buildPath(sourceB, sourceB, sourceA);
  dist = path.size()-1;
  int border = cautbinBorder(1, dist, sourceA, sourceB);
  int ans = solve(sourceA, sourceB, path[border-1], path[border]);
  //cerr << "  " << border-1 << ' ' << border << " - " << path[border-1] << ' ' << path[border] << '\n';
  if(border > 1) {
    ans = min(ans, solve(sourceA, sourceB, path[border-2], path[border-1])); 
  }
  if(border < dist) {
    ans = min(ans, solve(sourceA, sourceB, path[border], path[border+1]));
  }
  cout << ans << '\n';
  return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...