POJ 2114 - Boatherds

原题地址: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\n", ans[i] > 0 ? "AYE" : "NAY");
233         printf(".\n");
234     }
235 
236     return 0;
237 }

 

posted on 2014-04-17 22:13  SnowyJone  阅读(401)  评论(0编辑  收藏  举报