这真的算树形DP?
这是明显的求割点。
然后枚举siz子树,
利用正难则反的思想求答案
n*n-sigma SIZi^2
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<stack>
using namespace std;
typedef int INT;
#define int long long
int n,m;
const int N=5e5+100;
struct Front_star{
int u,v,nxt;
}e[N*3];
int cnt=0;
int first[N]={0};
void add(int u,int v){
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].nxt=first[u];
first[u]=cnt;
}
int color[N]={0};
int scc=0;
int dfn[N]={0};
int low[N]={0};
int dep[N]={0};
int SIZE[N]={0};
int pd[N]={0};
int siz=0;
int son=0;
stack<int> S;
void tarjan(int u,int fat){
siz++;
dfn[u]=siz;
low[u]=siz;
SIZE[u]=1;
dep[u]=dep[fat]+1;
S.push(u);
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
if(fat==v)
continue;
if(!dfn[v]){
tarjan(v,u);
low[u]=min(low[u],low[v]);
SIZE[u]+=SIZE[v];
if(low[v]>=dfn[u]){
pd[u]=1;
// if(dfn[u]==1)
// son++;
}
}
else{
low[u]=min(low[u],dfn[v]);
}
}
}
INT main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=m;i++){
int u,v;
scanf("%lld%lld",&u,&v);
add(u,v);
add(v,u);
}
tarjan(1,0);
// if(son==1)
for(int u=1;u<=n;u++){
if(pd[u]){
int sum1=1;
int sum2=1;
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
if(dep[v]==dep[u]+1&&low[v]>=dfn[u]){
sum1+=SIZE[v];
sum2+=SIZE[v]*SIZE[v];
}
}
sum2+=(n-sum1)*(n-sum1);
cout<<(n*n-sum2)<<'\n';
}
else{
cout<<(n-1)*2<<'\n';
}
}
}