hdu5016

题意:给定一个n个点的图,这个图是一棵树,然后有些点建立了集市。并且没有集市的地方去集市一定是去最近的,如果距离相同,那么则去标号最小的。。现在你还能在建一个集市,问建完这个集市最多有多少个点来这里。。

思路:

现对于每个点求该点到有标记点最近的距离,记录距离及其最近标号,可以用树形dp或者spfa搞。。

然后我们任意选定一个点建树,建完后进行点分治。。

对于当前分治快的跟rt,求rt到每个点的距离为dis,near为到标记点最近的距离

那么对于不同子树的点u,v,如果dis[u] + dis[v] < near[v],那么如果u建立集市v肯定到u。。

那么我们把式子变形下,dis[u] < near[v] - dis[v],对于u直接二分查找统计即可。。

我们可以先不管哪棵子树先统计一边,然后再减去相同的即可,这样写起来方便点。。写起来还蛮像poj1741的。。

code:

  1 /*
  2  * Author:  Yzcstc
  3  * Created Time:  2014/10/2 17:37:34
  4  * File Name: hdu5016.cpp
  5  */
  6 #pragma comment(linker, "/STACK:102400000,102400000")
  7 #include<cstdio>
  8 #include<iostream>
  9 #include<cstring>
 10 #include<cstdlib>
 11 #include<cmath>
 12 #include<algorithm>
 13 #include<string>
 14 #include<map>
 15 #include<set>
 16 #include<vector>
 17 #include<queue>
 18 #include<stack>
 19 #include<ctime>
 20 #define repf(i, a, b) for (int i = (a); i <= (b); ++i)
 21 #define repd(i, a, b) for (int i = (a); i >= (b); --i)
 22 #define M0(x)  memset(x, 0, sizeof(x))
 23 #define clr(x, y) memset(x, y, sizeof(x))
 24 #define N 120000
 25 #define Inf 0x3fffffff
 26 #define x first
 27 #define y second
 28 using namespace std;
 29 typedef pair<int, int> pii;
 30 struct edge{
 31      int v, w, next;
 32      edge(){}
 33      edge(int _v, int _w, int _next):v(_v), w(_w), next(_next){}
 34 } e[N<<1];
 35 int last[N], n, len, have[N], ans[N];
 36 int inq[N];
 37 pii ner[N];
 38
 39 void add(int u, int v, int w){
 40     e[len] = edge(v, w, last[u]), last[u] = len++;
 41 }
 42
 43 void init(){
 44      clr(last, -1);
 45      len = 0;
 46      int u, v, w;
 47      for (int i = 1; i < n; ++i){
 48           scanf("%d%d%d", &u, &v, &w);
 49           add(u, v, w), add(v, u, w);
 50      }
 51      repf(i, 1, n) scanf("%d", &have[i]);
 52 }
 53
 54 void gao(){
 55      repf(i, 0, n) ner[i].x = ner[i].y = Inf, inq[i] = 0;
 56      queue<int> q;
 57      repf(i, 1, n) if (have[i]){
 58            ner[i].x = 0, ner[i].y = i;
 59            q.push(i), inq[i] = 1;
 60      }
 61      int u, v;
 62      pii tmp;
 63      while (!q.empty()){
 64            u = q.front();
 65            q.pop(), inq[u] = 0;
 66            for (int p = last[u]; ~p; p = e[p].next){
 67                  v = e[p].v;
 68                  tmp.x = ner[u].x + e[p].w, tmp.y = ner[u].y;
 69                  if (tmp < ner[v]){
 70                         ner[v] = tmp;
 71                         if (!inq[v]) inq[v] = 1, q.push(v);
 72                  }
 73            }
 74      }
 75
 76 }
 77 /*** 点分治-begin **/
 78 int vis[N], sz, msize[N], f[N], size[N], belong[N], ss, ff[N];
 79 int dis[N];
 80 pair<int, int> s[N], tp;
 81
 82 void dfs(int u, int fa){ //calculate the size
 83      f[sz++] = u;
 84      msize[u] = 0, size[u] = 1;
 85      int v;
 86      for (int p = last[u]; ~p; p = e[p].next){
 87           v = e[p].v;
 88           if (v == fa || vis[v]) continue;
 89           dfs(v, u);
 90           size[u] += size[v];
 91           msize[u] = max(size[v], msize[u]);
 92      }
 93 }
 94
 95 void dfs(int u, int fa, int dist){
 96      dis[u] = dist, ff[ss++] = u;
 97      int v;
 98      for (int p = last[u]; ~p; p = e[p].next){
 99           v = e[p].v;
100           if (v == fa || vis[v]) continue;
101           dfs(v, u, dist + e[p].w);
102      }
103 }
104
105 void calculate(int u, int dist){
106      ss = 0;
107      dfs(u, 0, dist);
108      for (int i = 0; i < ss; ++i)
109           s[i].x = ner[ff[i]].x - dis[ff[i]], s[i].y = ner[ff[i]].y;
110      sort(s, s+ss);
111      int t;
112      for (int i = 0; i < ss; ++i) if (!have[ff[i]]){
113           tp.x = dis[ff[i]], tp.y = ff[i];
114           t = lower_bound(s, s+ss, tp) - s;
115           ans[ff[i]] += (dist > 0) ? (t - ss) : (ss - t);
116      }
117 }
118
119 void dfs(int u){
120      sz = 0;
121      dfs(u, 0);
122      int rt = 0, tmp, v;
123      for (int i = 0; i < sz; ++i){
124            tmp = max(msize[f[i]], sz-1-size[f[i]]);
125            if (tmp <= (sz>>1)) { rt = f[i]; break; }
126      }
127      calculate(rt, 0);
128      vis[rt] = 1;
129      for (int p = last[rt]; ~p; p = e[p].next){
130            v = e[p].v;
131            if (vis[v]) continue;
132            calculate(v, e[p].w);
133            dfs(v);
134      }
135 }
136 /**** 点分治-end***/
137
138 void solve(){
139      gao();
140      M0(vis);
141      M0(ans);
142      dfs(1);
143      int mx = 0;
144      for (int i = 1; i <= n; ++i)
145            mx = max(ans[i], mx);
146      printf("%d\n", mx);
147 }
148
149 int main(){
150 //    freopen("a.in", "r", stdin);
151 //    freopen("a.out", "w", stdout);
152     while (scanf("%d", &n) != EOF){
153           init();
154           solve();
155     }
156     return 0;
157 }

时间: 2024-10-25 00:08:33

hdu5016的相关文章

2014西安网络预选赛1009(点分治)HDU5016

Mart Master II Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 167    Accepted Submission(s): 63 Problem Description Trader Dogy lives in city S, which consists of n districts. There are n - 1

【点分治】hdu5016 Mart Master II

点分治好题. ①手动开栈. ②dp预处理每个点被哪个市场控制,及其距离是多少,记作pair<int,int>数组p. ③设dis[u].first为u到重心s的距离,dis[u].second=u,到在统计的时候,若dis[u]<=(p[v].first-dis[v].first,p[v].second)(双关键字比较),则符合题意,当然这样在计算同一颗子树里的答案时,是压根不对的,但是既然这部分反正是要被减掉的,那就将错就错地计算即可了. ④最后在所有原非市场节点的ans中取一个最大的