• poj1987 Distance Statistics


    普通dfs访问每个点对的复杂度是O(n^2)的,显然会超时。

    考虑访问到当前子树的根节点时,统计所有经过根的点(u, v)满足:

    dist(u) + dist(v) <= maxd,并且

    belong(u)≠belong(v)(即u,v不在同一子树)。

    这里说的距离指的是节点到跟的距离。

    可以用作差法,即用所有满足条件的点对数减去那些在根节点为当前子树根节点的儿子节点的点对数。

    上面一步可以用O(nlogn)的复杂度解决,即先排序再比较。

    根节点子树可以递归解决,用树的点分治。

    总复杂度上界是O(nlognlogn)。

    http://poj.org/problem?id=1987

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 using namespace std;
      5 const int maxn = 1e5 + 10;
      6 const int inf = 0x3f3f3f3f;
      7 struct Edge{
      8     int to, next, w;
      9 }edge[maxn << 1];
     10 int head[maxn], N;
     11 int n, m, maxd;
     12 bool vis[maxn];
     13 int cnt[maxn];
     14 int maxi[maxn];
     15 int ans;
     16 int mini, root, sum;
     17 int buf[maxn], k;
     18 
     19 void addEdge(int u, int v, int w){
     20     edge[N].next = head[u];
     21     edge[N].to = v;
     22     edge[N].w = w;
     23     head[u] = N++;
     24 }
     25 
     26 void init(){
     27     N = 0;
     28     memset(head, -1, sizeof head);
     29 }
     30 
     31 void get_cnt(int u){
     32     cnt[u] = 1;
     33     vis[u] = 1;
     34     maxi[u] = -1;
     35     buf[k++] = u;
     36     for(int i = head[u]; i + 1; i = edge[i].next){
     37         int v = edge[i].to;
     38         if(vis[v]) continue;
     39         get_cnt(v);
     40         cnt[u] += cnt[v];
     41         maxi[u] = max(maxi[u], cnt[v]);
     42     }
     43     vis[u] = 0;
     44 }
     45 
     46 void get_dist(int u, int d){
     47     vis[u] = 1;
     48     buf[k++] = d;
     49     for(int i = head[u]; i + 1; i = edge[i].next){
     50         int v = edge[i].to;
     51         if(vis[v]) continue;
     52         get_dist(v, d + edge[i].w);
     53     }
     54     vis[u] = 0;
     55 }
     56 
     57 int get_buf_sum(int left, int right){
     58     sort(buf + left, buf + right);
     59     int tem = 0;
     60     for(int i = right - 1, j = left; i >= left + 1; i--){
     61         while(j < i && buf[i] + buf[j] <= maxd) ++j;
     62         tem += min(i, j) - left;
     63     }
     64     return tem;
     65 }
     66 
     67 void cal(int u){
     68     k = 0;
     69     get_cnt(u);
     70     mini = inf;
     71     for(int i = 0; i < k; i++){
     72         int tem = max(cnt[u] - cnt[buf[i]], maxi[buf[i]]);
     73         if(tem < mini) mini = tem, root = buf[i];
     74     }
     75     k = 0;
     76     vis[root] = 1;
     77     int tem = 0;
     78     for(int i = head[root]; i + 1; i = edge[i].next){
     79         int v = edge[i].to;
     80         if(vis[v]) continue;
     81         int pre = k;
     82         get_dist(v, edge[i].w);
     83         tem -= get_buf_sum(pre, k);
     84     }
     85     buf[k++] = 0;
     86     tem += get_buf_sum(0, k);
     87     ans += tem;
     88     for(int i = head[root]; i + 1; i = edge[i].next){
     89         int v = edge[i].to;
     90         if(vis[v]) continue;
     91         cal(v);
     92     }
     93 }
     94 
     95 void solve(){
     96     scanf("%d", &maxd);
     97     memset(vis, 0, sizeof vis);
     98     ans = 0;
     99     for(int i = 1; i <= n; i++){
    100         if(!vis[i]) cal(i);
    101     }
    102     printf("%d
    ", ans);
    103 }
    104 
    105 int main(){
    106     //freopen("in.txt", "r", stdin);
    107     while(~scanf("%d", &n)){
    108         scanf("%d", &m);
    109         init();
    110         for(int i = 0, x, y, z; i < m; i++){
    111             scanf("%d%d%d", &x, &y, &z);
    112             addEdge(x, y, z);
    113             addEdge(y, x, z);
    114             getchar(), getchar();
    115         }
    116         solve();
    117     }
    118     return 0;
    119 }
    View Code
  • 相关阅读:
    Cookie、Session和自定义分页
    logstash 运行
    php json数据保留原样中文
    linux 32位还是64位
    php之isset 与 empty 区别
    php 订单
    个人分类
    laravel 创建自己的函数
    lumen框架导入数据异常
    yum安装samba服务器的安装
  • 原文地址:https://www.cnblogs.com/astoninfer/p/4882167.html
Copyright © 2020-2023  润新知