zoukankan      html  css  js  c++  java
  • POJ 2114

    原题地址:http://poj.org/problem?id=2114

    题目大意:

    给定一棵点数为(n~(n le 10000))的无根树,路径上有权值,给出m组询问($m le 100$),每组询问给出一个k,问树中是否存在长度为k的链。题目是多case

    题目分析:

    这是第二次写树分治,细节想清楚真的很重要啊。。。写了两天才写过,接下来说一说算法流程和需要注意的细节吧

    首先读入、建图等等等等。。

    然后是分治过程:

    0.如果当前处理的这棵树的size很小了,调用暴力解决,否则继续执行(这相当于边界处理)

    1.找出当前要处理的树的重心作为分治点

    2.算出重心到这棵树中每个点的距离,扫出来是否有两个点的距离和等于要询问的值,有则加上对数

    3.将重心发出的所有边断开,计算每棵子树中到重心距离和为k的点对,在答案中减去

    4.递归处理所有子树,根据最终得到的个数判断是否存在

    分治过程看起来很简单,但是有几个细节需要注意:断边的时候断开邻接表需要小心。每一次递归我们都需要初始化一些变量,但是每次全部初始化的代价过于高昂,而且会影响到当前树中没有的节点,每次初始化都BFS一遍过于麻烦,所有可以开若干个vector表示当前递归处理的子树中的点,然后就可以减少复杂度。计算距离之后需要排序去重以便高效地计算出要求的值。

    (准备省选过于忙碌了一直没来得及写什么总结……学了不少新知识回头都得抓紧总结了)

      1 //date 20140417
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 
      7 const int maxn = 10500;
      8 const int INF = 0x7FFFFFFF;
      9 const int r1 = 2;
     10 
     11 using namespace std;
     12 typedef vector<int> array;
     13 typedef array::iterator iter;
     14 typedef vector<array>::iterator viter;
     15 
     16 inline int getint()
     17 {
     18     int ans(0); char w = getchar();
     19     while(w < '0' || '9' < w)w = getchar();
     20     while('0' <= w && w <= '9')
     21     {
     22         ans = ans * 10 + w - '0';
     23         w = getchar();
     24     }
     25     return ans;
     26 }
     27 
     28 inline int innew(int &a, int b){if(a < b){a = b; return 1;}return 0;}
     29 inline int denew(int &a, int b){if(a > b){a = b; return 1;}return 0;}
     30 
     31 struct edge
     32 {
     33     int v, w, next;
     34 }E[maxn << 1];
     35 int a[maxn], nedge;
     36 int n;
     37 int ask[maxn], ans[maxn], nsk;
     38 
     39 vector<array> P;
     40 array tmp;
     41 
     42 inline void add(int u, int v, int w)
     43 {
     44     E[++nedge].v = v;
     45     E[nedge].w = w;
     46     E[nedge].next = a[u];
     47     a[u] = nedge;
     48 }
     49 
     50 namespace d_c
     51 {
     52     int yff, dis[maxn], list[maxn], size[maxn], p[maxn];
     53     int q[maxn], st, ed;
     54     int d[maxn], last, now[maxn], had[maxn];
     55     int tlist[maxn], ttot, plist[maxn];
     56     
     57     inline int getcend(int k, int yff)
     58     {
     59         for(iter i = P[k].begin(); i != P[k].end(); ++i)
     60         {
     61             size[*i] = p[*i] = 0; now[*i] = a[*i];
     62         }
     63         size[d[last = 1] = P[k][0]] = 1;
     64         while(last)
     65         {
     66             int i = d[last], j = now[i];
     67             if(!j)
     68             {
     69                 if(--last) size[d[last]] += size[i];
     70                 continue;
     71             }
     72             if(!size[E[j].v])
     73             {
     74                 size[d[++last] = E[j].v] = 1;
     75                 p[E[j].v] = i;
     76             }
     77             now[i] = E[j].next;
     78         }
     79         int Max, ans, Min = INF; 
     80         for(iter i = P[k].begin(); i != P[k].end(); ++i)
     81         {
     82             Max = yff - size[*i];
     83             for(int j = a[*i]; j; j = E[j].next)if(p[*i] != E[j].v)
     84                 innew(Max, size[E[j].v]);
     85             if(denew(Min, Max))ans = *i;
     86         }
     87         if(p[ans])size[p[ans]] = yff - size[ans];
     88         return ans;
     89     }
     90     
     91     inline void brutf(int k, int yff)
     92     {
     93         for(iter i = P[k].begin(); i != P[k].end(); ++i)
     94         {
     95             for(iter j = P[k].begin(); j != P[k].end(); ++j)dis[*j] = list[*j] = 0;
     96             int st = 0, ed = 1, tot;
     97             q[dis[*i] = 1] = *i;
     98             while(st < ed)
     99             {
    100                 int x = q[++st];
    101                 for(int i = a[x]; i; i = E[i].next)if(!dis[E[i].v])
    102                     dis[q[++ed] = E[i].v] = dis[x] + E[i].w;
    103             }
    104             for(iter j = P[k].begin(); j != P[k].end(); ++j)
    105                 for(int need = 1; need <= nsk; ++need)
    106                     ans[need] += (dis[*j] == ask[need] + 1) << 1;
    107         }
    108     }
    109     
    110     inline void main(int k)
    111     {
    112         yff = P[k].size();
    113         if(yff <= r1){brutf(k, yff); return;}
    114         int cend = getcend(k, yff);
    115         for(iter i = P[k].begin(); i != P[k].end(); ++i) dis[*i] = had[*i] = 0; 
    116         st = 0; ed = 1; int tot;
    117         list[dis[q[1] = cend] = tot = 1] = 1;
    118         while(st < ed)
    119         {
    120             int x = q[++st];
    121             for(int i = a[x]; i; i = E[i].next)if(!dis[E[i].v])
    122             {
    123                 list[++tot] = dis[q[++ed] = E[i].v] = dis[x] + E[i].w;
    124             }
    125         }
    126 
    127         sort(list + 1, list + tot + 1);
    128         tlist[plist[1] = ttot = 1] = list[1];
    129         for(int i = 2; i <= tot; ++i)
    130         {
    131             if(list[i] == list[i - 1])++plist[ttot];
    132             else {tlist[++ttot] = list[i]; plist[ttot] = 1;}
    133         }
    134         
    135         for(int need = 1; need <= nsk; ++need)
    136         {
    137             int j = ttot;
    138             for(int i = 1; i <= ttot; ++i)
    139             {
    140                 while(j && (tlist[j] + tlist[i] > ask[need] + 2))--j;
    141                 if(!j)break;
    142                 if(tlist[j] + tlist[i] == ask[need] + 2)
    143                 {
    144                     if(j != i)ans[need] += plist[i] * plist[j];
    145                     else ans[need] += plist[i] * (plist[i] - 1);
    146                 }
    147             }
    148         }
    149         
    150         for(int i = a[cend]; i; i = E[i].next)
    151         {
    152             int sign = 0;
    153             if(a[E[i].v] == (i ^ 1)){a[E[i].v] = E[i ^ 1].next;}
    154             else
    155             {
    156                 int last;
    157                 for(int j = a[E[i].v]; j != (i ^ 1); j = E[j].next) last = j;
    158                 E[last].next = E[i ^ 1].next;
    159             }
    160             tmp.clear(); 
    161             st = 0; ed = 1; q[had[E[i].v] = 1] = E[i].v;
    162             tmp.push_back(E[i].v);
    163             list[tot = 1] = dis[E[i].v];
    164             while(st < ed)
    165             {
    166                 int x = q[++st];
    167                 for(int j = a[x]; j; j = E[j].next)
    168                     if(!had[E[j].v]){tmp.push_back(E[j].v); had[E[j].v] = 1; q[++ed] = E[j].v; list[++tot] = dis[E[j].v];}
    169             }
    170             sort(list + 1, list + tot + 1);
    171             tlist[plist[1] = ttot = 1] = list[1];
    172             for(int w = 2; w <= tot; ++w)
    173             {
    174                 if(list[w] == list[w - 1])++plist[ttot];
    175                 else {tlist[++ttot] = list[w]; plist[ttot] = 1;}
    176             }
    177                     
    178             for(int need = 1; need <= nsk; ++need)
    179             {
    180                 int j = ttot;
    181                 for(int w = 1; w <= ttot; ++w)
    182                 {
    183                     while(j && (tlist[j] + tlist[w] > ask[need] + 2))--j;
    184                     if(!j)break;
    185                     if(tlist[w] + tlist[j] == ask[need] + 2)
    186                     {
    187                         if(j != w)ans[need] -= plist[w] * plist[j];
    188                         else ans[need] -= plist[w] * (plist[w] - 1);
    189                     }
    190                 }
    191             }
    192             
    193             P.push_back(tmp);
    194             main(P.size() - 1);
    195         }
    196         
    197     }
    198 }
    199 
    200 int main()
    201 {
    202     while(true)
    203     {
    204         n = getint();
    205         if(!n)break;
    206         P.clear(); tmp.clear();
    207         memset(a, 0, sizeof a);
    208         memset(ans, 0, sizeof ans);
    209         nedge = 1;
    210 
    211         for(int i = 1; i <= n; ++i)tmp.push_back(i);
    212         P.push_back(tmp);
    213         
    214         for(int i = 1; i <= n; ++i)
    215         {
    216             int x, w;
    217             while(true)
    218             {
    219                 x = getint();
    220                 if(!x)break;
    221                 w = getint();
    222                 add(i, x, w); add(x, i, w);
    223             }
    224         }
    225         nsk = 0;
    226         while(true)
    227         {
    228             ask[++nsk] = getint();
    229             if(!ask[nsk]){--nsk; break;}
    230         }
    231         d_c::main(0);
    232         for(int i = 1; i <= nsk; ++i)printf("%s
    ", ans[i] > 0 ? "AYE" : "NAY");
    233         printf(".
    ");
    234     }
    235 
    236     return 0;
    237 }
  • 相关阅读:
    系统运维易忘点总结之七
    SqlServer的排序规则
    Oracle数据库用户密码过期解决
    linux 查看即时网速 /流量的工具
    NFS部署过程
    NFS 共享存储
    Rsync服务的实战
    ncRsync服务
    架构名词
    状态码
  • 原文地址:https://www.cnblogs.com/w007878/p/3672063.html
Copyright © 2011-2022 走看看