zoukankan      html  css  js  c++  java
  • 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

       

  • 相关阅读:
    poj 2187 Beauty Contest(旋转卡壳)
    poj 2540 Hotter Colder(极角计算半平面交)
    poj 1279 Art Gallery(利用极角计算半平面交)
    poj 3384 Feng Shui(半平面交的联机算法)
    poj 1151 Atlantis(矩形面积并)
    zoj 1659 Mobile Phone Coverage(矩形面积并)
    uva 10213 How Many Pieces of Land (欧拉公式计算多面体)
    uva 190 Circle Through Three Points(三点求外心)
    zoj 1280 Intersecting Lines(两直线交点)
    poj 1041 John's trip(欧拉回路)
  • 原文地址:https://www.cnblogs.com/yzcstc/p/4027211.html
Copyright © 2011-2022 走看看