洛谷 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\n",2*(ans[i]+n-1)); 76 } 77 return 0; 78 }