• loj2587铁人两项


    无向图,图中选出定点三元组(a,b,c),a->b->c的路径没有重复边。问方案有多少?

    ————————————————————————————————————————————

    首先求出圆方树,方点权值为连接的圆点数量,圆点权值为-1

    这时,枚举a,c点,b点的方案数为a,c路径上的点权和。

    枚举a,c点然后计算点权和明显超时。于是我们枚举b点,计算通过它的方案数。

    所以神搜后有三种可能,b点的各个子分支与其它点,b点的向上分支与其它点,如果b点为a或c点的情况

    ————————————————————————————————————————————

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 2e5 + 10, maxm = 8e5 + 10;
     4 int n, m, cnt;
     5 struct edge {
     6     int u, v, nxt;
     7 } e[maxm], ee[maxm];
     8 int head[maxn], js, headd[maxn], jss;
     9 void addage(int u, int v) {
    10     e[++js].u = u;
    11     e[js].v = v;
    12     e[js].nxt = head[u];
    13     head[u] = js;
    14 }
    15 void addagee(int u, int v) {
    16     ee[++jss].u = u;
    17     ee[jss].v = v;
    18     ee[jss].nxt = headd[u];
    19     headd[u] = jss;
    20 }
    21 int dfn[maxn], low[maxn], tim, sta[maxn], top, pw[maxn];
    22 int sum, siz[maxn];
    23 bool vis[maxn];
    24 void tarjan(int u, int fa) {
    25     dfn[u] = low[u] = ++tim;
    26     sta[++top] = u;
    27     for (int i = head[u]; i; i = e[i].nxt) {
    28         int v = e[i].v;
    29         if (!dfn[v]) {
    30             tarjan(v, u);
    31             low[u] = min(low[v], low[u]);
    32             if (low[v] >= dfn[u]) {
    33                 cnt++;
    34                 int tp = 0;
    35                 while (tp != v) {
    36                     tp = sta[top--];
    37                     addagee(cnt, tp);
    38                     addagee(tp, cnt);
    39                     pw[cnt]++;
    40                     pw[tp] = -1;
    41                 }
    42                 addagee(cnt, u);
    43                 addagee(u, cnt);
    44                 pw[cnt]++;
    45                 pw[u] = -1;
    46             }
    47         } else if (v != fa)
    48             low[u] = min(low[u], dfn[v]);
    49     }
    50 }
    51 long long ans;
    52 void dfs1(int u, int fa) {
    53     vis[u] = 1;
    54     siz[u] = (u <= n);
    55     for (int i = headd[u]; i; i = ee[i].nxt) {
    56         int v = ee[i].v;
    57         if (v == fa)
    58             continue;
    59         dfs1(v, u);
    60         siz[u] += siz[v];
    61     }
    62 }
    63 void dfs2(int u, int fa) {
    64     for (int i = headd[u]; i; i = ee[i].nxt) {
    65         int v = ee[i].v;
    66         if (v == fa)
    67             continue;
    68         dfs2(v, u);
    69         ans += (long long)pw[u] * (sum - siz[v]) * siz[v];  // u的每一个子分支与其它点的
    70     }
    71     ans += (long long)pw[u] * (sum - siz[u]) * siz[u];  // u向上的分支与其它的点
    72     if (u <= n)
    73         ans += (long long)pw[u] * (sum - 1);  // u作为端点
    74 }
    75 int main() {
    76     scanf("%d%d", &n, &m);
    77     for (int u, v, i = 0; i < m; ++i) {
    78         scanf("%d%d", &u, &v);
    79         addage(u, v);
    80         addage(v, u);
    81     }
    82     cnt = n;
    83     for (int i = 1; i <= n; ++i)
    84         if (!dfn[i])
    85             tarjan(i, 0);
    86     for (int i = 1; i <= n; ++i)
    87         if (!vis[i]) {
    88             dfs1(i, 0);
    89             sum = siz[i];
    90             dfs2(i, 0);
    91         }
    92     cout << ans;
    93 
    94     return 0;
    95 }
    View Code
  • 相关阅读:
    第一次博客作业
    201771010110孔维滢《面向对象程序设计(java)》第二周学习总结
    孔维滢201771010110《面向对象程序设计(java)》第一周学习总结
    2018-2019-1 20165230《信息安全系统设计基础》第二周学习总结
    # 2018-2019-1 20165230 《信息安全系统设计基础》第三周学习总结
    20165230 获奖感想与学习心得
    20165230 2017-2018-2《Java程序设计》课程总结
    20165230 《Java程序设计》实验五《网络编程与安全》实验报告
    20165230 《Java程序设计》实验四 Android程序设计实验报告
    20165230 《Java程序设计》实验三 敏捷开发与XP实践 实验报告
  • 原文地址:https://www.cnblogs.com/gryzy/p/13140808.html
Copyright © 2020-2023  润新知