洛谷 P3469 [POI2008]BLO-Blockade 题解

一道经典的割点例题,用size数组记录该子树有多少个节点,sum是这棵搜索树上有多少个节点,sum*(n-sum-1)是将点删掉后的数对数量。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define maxn 1000010
 6 using namespace std;
 7 typedef long long ll;
 8 inline int read() 
 9 {
10     int x=0;
11     bool f=1;
12     char c=getchar();
13     for(; !isdigit(c); c=getchar()) if(c=='-') f=0;
14     for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0';
15     if(f) return x;
16     return 0-x;
17 }
18 inline void write(ll x)
19 {
20     if(x<0){putchar('-');x=-x;}
21     if(x>9)write(x/10);
22     putchar(x%10+'0');
23 }
24 struct node 
25 {
26     int to,nex;
27 }edge[maxn];
28 int dfn[maxn],low[maxn],st[maxn],inn[maxn],head[maxn],size[maxn];
29 int n,m,cnt,res,num;
30 ll ans[maxn];
31 inline void add(int u,int v)
32 {
33     cnt++;
34     edge[cnt].to=v;
35     edge[cnt].nex=head[u];
36     head[u]=cnt;
37 }
38 inline void Tarjan(int x,int root)
39 {
40     dfn[x]=low[x]=++num;
41     size[x]=1;
42     int flag=0,sum=0;
43     for(int i=head[x];i!=-1;i=edge[i].nex)
44     {
45         int y=edge[i].to;
46         if(!dfn[y])
47         {
48             Tarjan(y,root);
49             size[x]+=size[y];
50             low[x]=min(low[x],low[y]);
51             if(low[y]>=dfn[x]) 
52             {
53                 ans[x]+=(ll)sum*size[y];
54                 sum+=size[y];
55             }
56         }
57         else low[x]=min(low[x],dfn[y]);
58     }
59     ans[x]+=(ll)sum*(n-sum-1);
60 }
61 int main()
62 {
63     memset(head,-1,sizeof(head));
64     n=read();m=read();
65     for(int i=1;i<=m;i++)
66     {
67         int x,y;
68         x=read();y=read();
69         add(x,y);
70         add(y,x);
71     }
72     Tarjan(1,1);
73     for(int i=1;i<=n;i++)
74     {
75         printf("%lld
",2*(ans[i]+n-1));
76     }
77     return 0;
78 }
原文地址:https://www.cnblogs.com/handsome-zyc/p/11237749.html