• zoj3820


    题意:给定一个树,找出两个点,使得其他点到最近的点的距离最小

    思路:

        牡丹江站的B题。。可惜当时坑的不大对,最后也没写完。。

    1、题解方法:

       基于一个结论,答案一定在直径上(证明我不会)。。

       那么,可以先求出直径,然后直接二分,二分完后o(n)判定,时间复杂度为nlogn

    2、我的方法:

       赛场上写的,可惜最后由于各种原因没写完,代码难度实在比题解高多了,可惜想到了就不敢在猜想其他方法了了。。

       可以很容易证明,题目等价于对于删除某条边后求剩余两棵树直径,然后取一个最小的。。

       那么,就可以用树形dp的方法,维护每个点为子树的前三长链(以根为起始,并且来源于不同子树),还有不经过根的前两大答案,以及以其为根的子树的答案。

      先一边求完后,然后从根递推到以每个点为根成为一个树,其余为另外一棵树的答案啊。。

      这样时间复杂度为o(n)

    code(nlog(n)):

      1 #include <bits/stdc++.h>
      2 #define M0(a, b) memset(a, 0, sizeof(int) * (b+10))
      3 using namespace std;
      4 const int maxn = 210000;
      5 int z[maxn], inz[maxn], pos[maxn], from[maxn];
      6 int L[maxn], R[maxn], cov[maxn];
      7 vector<int> e[210000];
      8 int n, m;
      9 int ans, ansx, ansy;
     10 
     11 void init(){
     12     scanf("%d", &n);    
     13     for (int i = 0; i <= n; ++i)
     14         e[i].clear();
     15     int u, v;
     16     for (int i = 1; i < n; ++i){
     17          scanf("%d%d", &u, &v);
     18          e[u].push_back(v);
     19          e[v].push_back(u);
     20     }
     21 }
     22 
     23 int pre[maxn], inq[maxn], dis[maxn];
     24 void bfs(int s, int &rt){
     25     queue<int> q;
     26     M0(inq, n), M0(dis, n), M0(pre, n);
     27     q.push(s), dis[s] = 0, inq[s] = 1;
     28     int u, v;
     29     while (!q.empty()){
     30          u = q.front();
     31          q.pop();
     32          for (int i = 0; i < (int)e[u].size(); ++i){
     33                v = e[u][i];
     34                if (!inq[v])
     35                     dis[v] = dis[u] + 1, inq[v] = 1, q.push(v), pre[v] = u;
     36          }
     37     }
     38     rt = s;
     39     for (int i = 1; i <= n; ++i)
     40         if (dis[rt] < dis[i]) rt = i;
     41 }
     42 
     43 void bfs(){
     44     queue<int> q;
     45     M0(inq, n), M0(dis, n), M0(from, n);
     46     for (int i = 1; i <= m; ++i)
     47         q.push(z[i]), inq[z[i]] = 1, from[z[i]] = i, dis[z[i]] = 0;
     48     int u, v;
     49     while (!q.empty()){
     50          u = q.front();
     51          q.pop();
     52          for (int i = 0; i < (int)e[u].size(); ++i){
     53                v = e[u][i];
     54                if (!inq[v])
     55                     dis[v] = dis[u] + 1, inq[v] = 1, q.push(v), from[v] = from[u];
     56          }
     57     }
     58 }
     59 
     60 
     61 int check(const int len, int& x, int &y){
     62     M0(L, n), M0(R, n), M0(cov, n);
     63     int d;
     64     int mleft = m + 1, mright = 0;
     65     for (int i = 1; i <= n; ++i){
     66          d = len - dis[i];
     67          if (d < 0) return 0;
     68          L[i] = max(1, from[i] - d);
     69          R[i] = min(m, from[i] + d);
     70          mleft = min(mleft, R[i]);
     71          mright = max(mright, L[i]);
     72     }
     73     for (int i = 1; i <= n; ++i)
     74        if ((L[i] <= mleft && R[i] >= mleft) || (L[i] <= mright && R[i] >= mright)) continue;
     75        else return 0;
     76     x = mleft, y = mright;
     77     if (x == y) 
     78          (y < m) ?  ++y :  --x;
     79     return 1; 
     80 }
     81 
     82 void solve(){
     83     int s, t;
     84     bfs(1, s), bfs(s, t);
     85     m = 0;
     86     M0(inz, n), M0(pos, n);
     87     while (t) z[++m] = t, pos[t] = m, t = pre[t];
     88     bfs();
     89     int l = 0, r = n, mid;
     90     int x, y;
     91     while (l <= r){
     92          mid = (l + r) >> 1;
     93          if (check(mid, x, y)) 
     94                r = mid - 1, ans = mid, ansx = z[x], ansy = z[y];
     95          else l = mid + 1;
     96     }
     97     printf("%d %d %d
    ", ans, ansx, ansy);
     98 }
     99 
    100 int main(){
    101     int cas;
    102     scanf("%d", &cas);    
    103     while (cas--){
    104         init();
    105         solve();
    106     }
    107 }
    View Code

    code(o(n)):

      1 #include <bits/stdc++.h>
      2 #define x first
      3 #define y second
      4 #define M0(a) memset(a, 0, sizeof(int) * (n+10))
      5 #define Inf 0x3fffffff
      6 using namespace std;
      7 const int maxn = 210000;
      8 vector<int> e[maxn];
      9 pair<int, int> len[maxn][3], ans2[maxn][2], tmp[10], one(1, 0), zero(0, 0);
     10 int fa[maxn], ans1[maxn], n, ans[maxn], z[maxn];
     11 int ans_x, ans_y, ans_len;
     12 
     13 int inq[maxn], dis[maxn], pre[maxn];
     14 int pos[maxn], tot;
     15 void bfs(){
     16      M0(inq), M0(fa);
     17      queue<int> q;
     18      q.push(1), inq[1] = 1, pos[tot = 1] = 1;
     19      int u, v;
     20      while (!q.empty()){
     21           u = q.front();
     22           q.pop();
     23           for (int i = 0; i < (int)e[u].size(); ++i){
     24                v = e[u][i];
     25                if (!inq[v])
     26                     fa[v] = u, q.push(v), inq[v] = 1, pos[++tot] = v; 
     27           }
     28      }     
     29 }
     30 
     31 void gao1(const int& u){
     32      int v;
     33      for (int i = 0; i < (int)e[u].size(); ++i){
     34          v = e[u][i];
     35          if (v == fa[u]) continue;
     36          for (int j = 0; j < 3; ++j) tmp[j] = len[u][j];
     37          tmp[3] = make_pair(len[v][0].x + 1, v);
     38          sort(tmp, tmp + 4, greater<pair<int, int> >());
     39          for (int j = 0; j < 3; ++j) len[u][j] = tmp[j];
     40          if (ans1[v] > ans2[u][0].x){
     41               swap(ans2[u][1], ans2[u][0]);
     42               ans2[u][0] = make_pair(ans1[v], v);
     43          } else if (ans1[v] > ans2[u][1].x)
     44               ans2[u][1] = make_pair(ans1[v], v);
     45          ans1[u] = max(ans1[u], ans1[v]); 
     46      }
     47      ans1[u] = max(ans1[u], len[u][0].x + len[u][1].x - 1);
     48 }
     49 
     50 int ff, s[5];
     51 int ss[maxn], max_d[maxn];
     52 void gao2(const int &u){
     53      ff = fa[u];
     54      ss[u] = ss[ff];
     55      if (len[ff][0].y == u)
     56          s[0] = len[ff][1].x, s[1] = len[ff][2].x;
     57      else if (len[ff][1].y == u)
     58          s[0] = len[ff][0].x, s[1] = len[ff][2].x;
     59      else 
     60          s[0] = len[ff][0].x, s[1] = len[ff][1].x;
     61      s[2] = max_d[ff];
     62      sort(s, s + 3, greater<int>() );
     63      ss[u] = max(s[0] + s[1] - 1, ss[u]);
     64      max_d[u] = s[0] + 1;
     65      if (ans2[ff][0].y == u)
     66          ss[u] = max(ss[u], ans2[ff][1].x);
     67      else 
     68          ss[u] = max(ss[u], ans2[ff][0].x);
     69      ans[u] = max(ss[u], ans1[u]);
     70 }
     71 
     72 void pre_do(){
     73     M0(ss), M0(max_d);
     74     for (int i = 0; i <= n; ++i){
     75           len[i][0] = len[i][1] = len[i][2] = one;
     76           ans2[i][0] = ans2[i][1] = zero;
     77     }
     78 }
     79 
     80 void init(){
     81      scanf("%d", &n);
     82      pre_do();
     83      for (int i = 0; i <= n; ++i) 
     84           e[i].clear();
     85      int u, v;
     86      for (int i = 1; i < n; ++i){
     87          scanf("%d%d", &u, &v);
     88          e[u].push_back(v);
     89          e[v].push_back(u);
     90      }
     91 }
     92 
     93 void bfs(int s, int &t, const int& other){
     94     queue<int> q;
     95     M0(inq),  M0(pre);
     96     memset(dis, -1, sizeof(int) * (n+10));
     97     q.push(s), dis[s] = 0, inq[s] = 1;
     98     int u, v;
     99     while (!q.empty()){
    100          u = q.front();
    101          q.pop();
    102          for (int i = 0; i < (int)e[u].size(); ++i){
    103                v = e[u][i];
    104                if (v == other) continue;
    105                if (!inq[v])
    106                     dis[v] = dis[u] + 1, inq[v] = 1, q.push(v), pre[v] = u;
    107          }
    108     }
    109     t = s;
    110     for (int i = 1; i <= n; ++i)
    111         if (dis[t] < dis[i]) t = i;
    112 }
    113 
    114 void solve(){
    115      M0(fa), M0(ans1);
    116      bfs();
    117      for (int i = n; i >= 1; --i)
    118           gao1(pos[i]);
    119      for (int i = 2; i <= n; ++i)
    120           gao2(pos[i]);
    121      int rt = 2;
    122      for (int i = 2; i <= n; ++i)
    123           if (ans[rt] > ans[i]) rt = i;
    124 //     cout << rt << endl;
    125      ans_len = ans[rt] / 2;
    126      int x, y;
    127      bfs(rt, x, fa[rt]);
    128      bfs(x, y, fa[rt]);
    129      int m = 0;
    130      while (y) z[m++] = y, y = pre[y];
    131      ans_x = z[m/2];
    132      bfs(fa[rt], x, rt);
    133      bfs(x, y, rt);
    134      m = 0;
    135      while (y) z[m++] = y, y = pre[y];
    136      ans_y = z[m/2];
    137      printf("%d %d %d
    ",ans_len, ans_x, ans_y);
    138      
    139 }
    140 
    141 int main(){
    142     int cas;
    143     scanf("%d", &cas);
    144     while (cas--){
    145           init();
    146           solve();        
    147     } 
    148 }    
    View Code

       

  • 相关阅读:
    路由系统整合
    python操作excel
    Django models ORM基础操作--白话聊Django系列
    Django视图views--白话聊Django系列
    Django分发控制器urls--白话聊Django系列
    HTML页面布局
    一篇搞定SQLAlchemy--关系对象映射
    [LC] 538. Convert BST to Greater Tree
    [LintCode] 535. House Robber III
    [Algo] Rotate String
  • 原文地址:https://www.cnblogs.com/yzcstc/p/4027211.html
Copyright © 2020-2023  润新知