zoukankan      html  css  js  c++  java
  • BZOJ1123:[POI2008]BLO(双连通分量)

    Description

    Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通。

    Input

    输入n<=100000 m<=500000及m条边

    Output

    输出n个数,代表如果把第i个点去掉,将有多少对点不能互通。

    Sample Input

    5 5
    1 2
    2 3
    1 3
    3 4
    4 5

    Sample Output

    8
    8
    16
    14
    8

    Solution

    题意不清楚。点对(x,y)!=(y,x),且去掉的点也要考虑进答案
    当我们dfs找割点的时候,会形成一颗dfs树
    对于一个割点x,若将其去掉,可以分成x上面的一颗子树和x的若干子树
    Tarjan的时候乘法原理统计一下答案即可

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #define N (100000+1000)
     5 #define M (500000+1000)
     6 using namespace std;
     7 
     8 struct Edge{int from,to,next;}edge[M<<1];
     9 int n,m,u,v,head[N],num_edge;
    10 int Dfn[N],Low[N],dfs_num,Cut[N];
    11 long long size[N],ans[N];
    12 
    13 void add(int u,int v)
    14 {
    15     edge[++num_edge].from=u;
    16     edge[num_edge].to=v;
    17     edge[num_edge].next=head[u];
    18     head[u]=num_edge;
    19 }
    20 
    21 void Tarjan(int x,int fa)
    22 {
    23     long long son_num=0,sum=0;
    24     size[x]=1;
    25     Dfn[x]=Low[x]=++dfs_num;
    26     for (int i=head[x]; i; i=edge[i].next)
    27         if (!Dfn[edge[i].to])
    28         {
    29             son_num++;
    30             Tarjan(edge[i].to,x);
    31             size[x]+=size[edge[i].to];
    32             Low[x]=min(Low[x],Low[edge[i].to]);
    33             if (Low[edge[i].to]>=Dfn[x])
    34             {
    35                 Cut[x]=true;
    36                 ans[x]+=sum*size[edge[i].to];
    37                 sum+=size[edge[i].to];
    38             }
    39         }
    40         else
    41             if (Dfn[x]>Dfn[edge[i].to] && edge[i].to!=fa)
    42                 Low[x]=min(Low[x],Dfn[edge[i].to]);
    43     if (fa==0 && son_num==1)
    44         Cut[x]=false;
    45     if (Cut[x]) ans[x]+=sum*(n-sum-1);
    46 }
    47 
    48 int main()
    49 {
    50     scanf("%d%d",&n,&m);
    51     for (int i=1; i<=m; ++i)
    52     {
    53         scanf("%d%d",&u,&v);
    54         add(u,v); add(v,u);
    55     }
    56     for (int i=1; i<=n; ++i)
    57         if (!Dfn[i])
    58             Tarjan(i,0);
    59     for (int i=1; i<=n; ++i)
    60         printf("%lld
    ",(long long)(ans[i]+n-1)*2);
    61 }
  • 相关阅读:
    linux 命令——19 find (转)
    linux 命令——18 locate (转)
    linux 命令——17 whereis(转)
    linux 命令——16 which(转)
    linux 命令——15 tail (转)
    linux 命令——14 head (转)
    Java for LeetCode 038 Count and Say
    Java for LeetCode 037 Sudoku Solver
    Java for LeetCode 036 Valid Sudoku
    Java for LeetCode 035 Search Insert Position
  • 原文地址:https://www.cnblogs.com/refun/p/9289140.html
Copyright © 2011-2022 走看看