码迷,mamicode.com
首页 > 其他好文 > 详细

【校内训练2019-11-10】无聊的日常

时间:2019-11-10 15:44:07      阅读:91      评论:0      收藏:0      [点我收藏+]

标签:def   oid   fir   限制   推导   turn   inline   root   距离   

【题目概括】

\(n\)个点的树,边权均为\(1\),求任意一个点\(x\)满足\(M\)条限制。

\(i\)条限制为“\(x\)到节点\(A_i\)的距离加上\(x\)到节点\(B_i\)的距离不超过\(D_i\)”。

【思路要点】

  • 对于每一个限制都构造一个变量\(W_i=max(0,\frac {dep[A_i]+dep[B_i]-D_i}2)\)
  • 可以推导得,\(x\)节点满足:\(\forall i,dep[x]\ge w_i\)
  • 那么我们就只需要满足\(dep[x]\ge max\{ W_i\}\)
  • 找到满足条件的深度最浅的点\(x\),一定是最优的点。
  • 如果限制条件都在\(x\)的子树内,那么一定是满足的,因为下面的限制已经将上面不满足的点都去掉了。
  • 如果限制条件都在\(x\)的子树外,那么一定是先通过\(x\)点,然后再到子树内的节点。
  • 如果限制条件分别在子树内和子树外,那么这个点\(x\)一定是在两个限制条件节点的简单路径上。
  • 那么我们找到这个深度最小的节点,然后再做一遍深搜,就可以得到答案了。

【代码】

#include <bits/stdc++.h>

#define FI first
#define SE second
#define REP(i, s, t) for (int i = s; i <= t; i++)
#define PER(i, s, t) for (int i = s; i >= t; i--)
#define pb push_back
#define mp make_pair

using namespace std;

template <class T> void chkmax(T& x, T y) { x = max(x, y); }
template <class T> void chkmin(T& x, T y) { x = min(x, y); }

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

inline char gc() {
  static char buf[1 << 25], *p1 = buf, *p2 = buf;
  return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 25, stdin), p1 == p2) ? EOF : *p1++;
}

template <class T>
void re(T& x) {
  x = 0; char ch = 0; int f = 1;
  for (; !isdigit(ch); ch = gc()) if (ch == '-') f = -1;
  for (; isdigit(ch); ch = gc()) x = x * 10 + ch - 48;
  x *= f;
}

const int N = 1e6 + 5;

int n, m, mx, lim;
vector<int> G[N];
struct Query {
  int u, v, x, w;
} qry[N];
int dep[N][4];

void dfs(int u, int fff, int opt) {
  for (auto v : G[u]) {
    if (v == fff)
      continue;
    dep[v][opt] = dep[u][opt] + 1;
    dfs(v, u, opt);
  }
}

int main() {
  re(n), re(m);
  for (int i = 1; i < n; i++) {
    int u, v; re(u), re(v);
    G[u].pb(v), G[v].pb(u);
  }
  dfs(1, 0, 0);
  for (int i = 1; i <= m; i++) {
    re(qry[i].u), re(qry[i].v), re(qry[i].x);
    qry[i].w = max(0, dep[qry[i].u][0] + dep[qry[i].v][0] - qry[i].x);
    chkmax(mx, qry[i].w);
  }
  for (int i = 1; i <= m; i++) 
    if (qry[i].w == mx) {
      dfs(qry[i].u, 0, 1), dfs(qry[i].v, 0, 2);
      lim = qry[i].x;
      break;
    }
  int root = 0;
  for (int i = 1; i <= n; i++) 
    if (dep[i][1] + dep[i][2] <= lim && (!root || dep[root][0] > dep[i][0]))
      root = i; 
  dfs(root, 0, 3);
  for (int i = 1; i <= m; i++)
    if (dep[qry[i].u][3] + dep[qry[i].v][3] > qry[i].x) {
      printf("NO\n");
      return 0;
    }
  printf("%d\n", root);
  return 0;
}

【校内训练2019-11-10】无聊的日常

标签:def   oid   fir   限制   推导   turn   inline   root   距离   

原文地址:https://www.cnblogs.com/chhokmah/p/11830246.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!