zoukankan      html  css  js  c++  java
  • 【APIO 2018】铁人两项(圆方树)

    题目链接

    题意大概是,求有多少三元组$(s,c,f)(s eq c, c eq f, s eq f)$,满足从$s$到$f$有一条简单路径经过$c$。

    得到结论:

    1. 点双中任意互不相同的三个点,必定存在一条简单路径依次经过这三个点。
    2. 显然,割点只能经过一次。

    建出一棵圆方树,圆点的权值为$-1$,方点的权值为该点双中点的个数,那任意两个圆点之间可以作为它们中转点的个数就是它们在圆方树上路径的点权和。

    具体来讲就是割点上只能经过一次,圆点设成$-1$是为了去重方便。

    以前只写过点双缩树,这里写圆方树更方便,权且将这道题作为学习的例题吧。

    建圆方树只要在Tarjan上稍作修改,这里给出建树的例子:

    void Tarjan(int x, int fa) {
        sta[++top] = x; in[x] = -1;
        dfn[x] = low[x] = ++_clock;
        for (int i = las[x]; i; i = pre[i]) {
            if (to[i] == fa) continue;
            if (dfn[to[i]]) {
                low[x] = std::min(low[x], dfn[to[i]]);
            } else {
                Tarjan(to[i], x);
                low[x] = std::min(low[x], low[to[i]]);
                if (dfn[x] <= low[to[i]]) {
                    xtr[x].push_back(++c_n); ++in[c_n];
                    for (int t = -1; t != to[i]; ) {
                        t = sta[top--];
                        xtr[c_n].push_back(t); ++in[c_n];
                    }
                }
            }
        }
    }
    View Code

    (注:xtr为圆方树,in < 0代表圆点,否则代表了该方点中点双里点的个数)

    之后这个题就好做了,统计的是所有圆点点对间路径长度的总和。

     1 #include <cstdio>
     2 #include <vector>
     3 #include <iostream>
     4 
     5 typedef long long LL;
     6 const int N = 200005;
     7 
     8 int n, m;
     9 int dfn[N], low[N], in[N], siz[N], sta[N], top, _clock, c_n;
    10 std::vector<int> xtr[N];
    11 LL ans, sum[N];
    12 
    13 int yun = 1, las[N], to[N << 1], pre[N << 1];
    14 inline void Add(int a, int b) {
    15     to[++yun] = b; pre[yun] = las[a]; las[a] = yun;
    16 }
    17 
    18 void Tarjan(int x, int fa) {
    19     sta[++top] = x; in[x] = -1;
    20     dfn[x] = low[x] = ++_clock;
    21     for (int i = las[x]; i; i = pre[i]) {
    22         if (to[i] == fa) continue;
    23         if (dfn[to[i]]) {
    24             low[x] = std::min(low[x], dfn[to[i]]);
    25         } else {
    26             Tarjan(to[i], x);
    27             low[x] = std::min(low[x], low[to[i]]);
    28             if (dfn[x] <= low[to[i]]) {
    29                 xtr[x].push_back(++c_n); ++in[c_n];
    30                 for (int t = -1; t != to[i]; ) {
    31                     t = sta[top--];
    32                     xtr[c_n].push_back(t); ++in[c_n];
    33                 }
    34             }
    35         }
    36     }
    37 }
    38 
    39 void Dfs(int x) {
    40     if (in[x] < 0) siz[x] = 1, sum[x] = in[x];
    41     for (int i = 0; i < (int)xtr[x].size(); ++i) {
    42         int v = xtr[x][i];
    43         Dfs(v);
    44         siz[x] += siz[v];
    45         sum[x] += (LL) siz[v] * in[x] + sum[v];
    46     }
    47 }
    48 void Calc(int x) {
    49     if (in[x] < 0) ans += sum[x] - in[x];
    50     LL cnt = 0;
    51     for (int i = 0; i < (int)xtr[x].size(); ++i) {
    52         int v = xtr[x][i];
    53         ans += (LL) sum[v] * (siz[x] - (in[x] < 0) - siz[v]);
    54         cnt += (LL) siz[v] * (siz[x] - (in[x] < 0) - siz[v]);
    55     }
    56     ans += (LL) cnt / 2 * in[x];
    57     for (int i = 0; i < (int)xtr[x].size(); ++i) {
    58         int v = xtr[x][i];
    59         Calc(v);
    60     }
    61 }
    62 
    63 int main() {
    64     scanf("%d%d", &n, &m);
    65     c_n = n;
    66     for (int i = 1, x, y; i <= m; ++i) {
    67         scanf("%d%d", &x, &y);
    68         Add(x, y); Add(y, x);
    69     }
    70     for (int i = 1; i <= n; ++i) {
    71         if (!dfn[i]) {
    72             Tarjan(i, 0);
    73             Dfs(i);
    74             Calc(i);
    75         }
    76     }
    77     printf("%lld
    ", ans * 2);
    78     
    79     return 0;
    80 }
    View Code

    $igodot$技巧&套路:

    • 圆方树的构建,圆方树上的统计技巧,可以用圆点的权值设成$-1$来去重。
  • 相关阅读:
    [原创] Python3.6+request+beautiful 半次元Top100 爬虫实战,将小姐姐的cos美图获得
    手算平方根和基于 Java BigInteger 的大整数平方根的实现
    Spyder项目创建,打开与使用
    手动实现自己的spring事务注解
    springboot2.x配置druid sql监控
    基于zookeeper实现分布式锁
    数据库中间件之mycat读写分离
    springboot + shiro 构建权限模块
    数据库中间件之mycat安装部署(一)
    使用jdk8 stream简化集合操作
  • 原文地址:https://www.cnblogs.com/Dance-Of-Faith/p/9327129.html
Copyright © 2011-2022 走看看