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

       

  • 相关阅读:
    【校招面试 之 C/C++】第23题 C++ STL(五)之Set
    Cannot create an instance of OLE DB provider “OraOLEDB.Oracle” for linked server "xxxxxxx".
    Redhat Linux安装JDK 1.7
    ORA-10635: Invalid segment or tablespace type
    Symantec Backup Exec 2012 Agent for Linux 卸载
    Symantec Backup Exec 2012 Agent For Linux安装
    You must use the Role Management Tool to install or configure Microsoft .NET Framework 3.5 SP1
    YourSQLDba介绍
    PL/SQL重新编译包无反应
    MS SQL 监控数据/日志文件增长
  • 原文地址:https://www.cnblogs.com/yzcstc/p/4027211.html
Copyright © 2011-2022 走看看