• BZOJ1123 [POI2008]BLO(割点判断 + 点双联通缩点size)


     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 using namespace std;
     5 
     6 typedef long long ll;
     7 const int maxn = 1e5 + 5;
     8 const int maxm = 5e5 + 5;
     9 int dfn[maxn], low[maxn], head[maxn];
    10 ll ans[maxn], siz[maxn];
    11 int n, m, tot, num, root;
    12 bool cut[maxn];
    13 struct edge{
    14     int to, next;
    15 } ed[2*maxm];
    16 inline void init(){
    17     memset( head, -1, sizeof(head) );
    18     memset( dfn, 0, sizeof(dfn) );
    19     memset( cut, false, sizeof(cut) );
    20     memset( ans, 0, sizeof(ans) );
    21     num = 0;
    22     tot = 1;
    23 }
    24 
    25 inline int min( int a, int b ){
    26     return a<b ? a:b;
    27 }
    28 
    29 inline void add( int u, int v ){
    30     tot ++;
    31     ed[tot].to = v;
    32     ed[tot].next = head[u];
    33     head[u] = tot;
    34 }
    35 
    36 inline void tarjan( int u ){
    37     dfn[u] = low[u] = ++num;
    38     siz[u] = 1;
    39     int flag = 0, sum = 0;
    40     for( int i=head[u]; i!=-1; i=ed[i].next ){
    41         int v = ed[i].to;
    42         if( !dfn[v] ){
    43             tarjan(v);
    44             siz[u] += siz[v];      //计算子树的点个数
    45             low[u] = min(low[u], low[v]);
    46             if( dfn[u]<=low[v] ){
    47                 flag ++;
    48                 ans[u] += (ll)siz[v]*(n-siz[v]);    //if(cut[i]) ans = (i的子树, 除该子树的其他部分)的点对和
    49                 sum += siz[v];
    50                 if( u!=root || flag>1 ) cut[u] = true;
    51             }
    52         }else low[u] = min(low[u], dfn[v]);
    53     }
    54     if( cut[u] ) ans[u] += (ll)(n-sum-1)*(sum+1) + (n-1);  //如果去掉的点i是割点ans继续累加上(其他部分,i和i的子树)点对 + (i, 除i的其他部分)点对
    55     else ans[u] = 2*(n-1);              //if(!cut[i]) ans = 2*(n-1)
    56 }
    57 
    58 int main(){
    59     scanf("%d%d", &n, &m);
    60     init();
    61     for( int i=0; i<m; i++ ){
    62         int u, v;
    63         scanf("%d%d", &u, &v);
    64         add( u, v );
    65         add( v, u );
    66     }
    67     root = 1;
    68     tarjan(1);
    69     for( int i=1; i<=n; i++ )
    70         printf("%lld
    ", ans[i]);
    71 
    72     return 0;
    73 }
    74 /*Sample Input
    75 5 5
    76 1 2
    77 2 3
    78 1 3
    79 3 4
    80 4 5
    81 Sample Output
    82 8
    83 8
    84 16
    85 14
    86 8
    87 */
  • 相关阅读:
    关于Socket.IO
    关于js的执行与加载
    关于XSS
    关于浏览器的渲染过程
    关于高级前端的面试题
    关于js的设计模式(简单工厂模式,构造函数模式,原型模式,混合模式,动态模式)
    关于js的高级函数(惰性函数,函数柯里化,级联函数)
    关于map
    bzoj 2744: [HEOI2012]朋友圈 二分图匹配
    bzoj 3637: Query on a tree VI 树链剖分 && AC600
  • 原文地址:https://www.cnblogs.com/WAautomaton/p/10843920.html
Copyright © 2020-2023  润新知