割点判断+luogu 3469 POI2008 BLO
1.根节点,有2棵及以上子树
2.非根节点,有子节点dfn[u]<=low[v]
#include <bits/stdc++.h> #define N 1000050 using namespace std; inline int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int head[N],dfn[N],low[N],cut[N]; int cnt,idx; struct node{int v,next;}e[2*N]; void insert(int u,int v){ e[++cnt]=(node){v,head[u]};head[u]=cnt; e[++cnt]=(node){u,head[v]};head[v]=cnt; } void tarjan(int u,int f){ dfn[u]=low[u]=++idx; int rs=0; for(int i=head[u];i;i=e[i].next){ int v=e[i].v; if(!dfn[v]){ tarjan(v,f);rs++; low[u]=min(low[u],low[v]); if((u==f&&2<=rs)||(u!=f&&dfn[u]<=low[v])) cut[u]=1; }else low[u]=min(low[u],dfn[v]); } } int n,m,ans; int main(){ n=read(),m=read(); for(int i=1;i<=m;i++){ int x=read(),y=read(); insert(x,y); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,i); for(int i=1;i<=n;i++) if(cut[i]) ans++; printf("%d\n",ans); for(int i=1;i<=n;i++) if(cut[i]) printf("%d ",i); return 0; }
割点+树形dp
在同一连通块内用z累计大小(除u节点)
判断割点并累加内部答案,
最后累加连通块内部与外界答案
树形dp+割点tarjan
#include<bits/stdc++.h> #define ll long long const int N=100050; const int M=1000050; using namespace std; int dfn[N],low[N],siz[N],cut[N]; ll ans[N]; inline int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f;} int head[N],tot,idx,n,m,x,y; struct node{int v,next;}e[M]; void insert(int u,int v){ e[++tot]=(node){v,head[u]};head[u]=tot; e[++tot]=(node){u,head[v]};head[v]=tot;} int tarjan(int u){ int z=0;siz[u]=1; dfn[u]=low[u]=++idx; for(int i=head[u];i;i=e[i].next){ int v=e[i].v; if(!dfn[v]){ tarjan(v); siz[u]+=siz[v]; low[u]=min(low[u],low[v]); if(dfn[u]<=low[v]){ ans[u]+=(ll)z*siz[v]; z+=siz[v];} //连通块内部的累加答案 }else low[u]=min(low[u],dfn[v]); }ans[u]+=(ll)z*(n-z-1);//此连通块内部和外部(除本节点)的累加答案 } int main(){ n=read();m=read(); for(int i=1;i<=m;i++) x=read(),y=read(),insert(x,y); tarjan(1); for(int i=1;i<=n;i++) printf("%lld\n",(ans[i]+n-1)<<1);return 0; }