先建出圆方树,题目转换为数长度为 \(2*L-1\) 的路径数,长链剖分
code
#include<bits/stdc++.h>
using namespace std;
#define N 2000005
#define ll long long
int n,m,top,tot,cnt,L,k;
int dfn[N],low[N],zhan[N],h[N];
struct AB{
int a,b,n;
}d[N*4];
void cun(int x,int y){
d[++k]=(AB){x,y,h[x]},h[x]=k;
}
namespace CP{
int k,h[N*2];
AB d[N*4];
int hei[N*2],son[N*2];
ll *f[N*2],*las;
ll pos[N*4],ans;
void cun(int x,int y){
d[++k]={x,y,h[x]},h[x]=k;
d[++k]={y,x,h[y]},h[y]=k;
}
void dfs(int x,int fa){
hei[x]=1;
for(int i=h[x];i;i=d[i].n){
int y=d[i].b;
if(y==fa) continue;
dfs(y,x);
if(hei[y]+1>hei[x]) hei[x]=hei[y]+1,son[x]=y;
}
}
void DP(int x,int fa){
if(son[x]){
f[son[x]]=f[x]+1;
DP(son[x],x);
}
if(x<=n) f[x][1]=1;
if(hei[x]>=L) ans+=f[x][L];
for(int i=h[x];i;i=d[i].n){
int y=d[i].b;
if(y==fa||y==son[x]) continue;
f[y]=las,las=las+hei[y]+1;
DP(y,x);
for(int j=1;j<=hei[y];j++){
if(j<=L&&L-j<=hei[x]) ans+=f[y][j]*f[x][L-j];
}
for(int j=1;j<=hei[y];j++) f[x][j+1]+=f[y][j];
}
}
void solve(){
dfs(1,0);L=L*2-1;
f[1]=pos;
las=pos+hei[1]+1;
DP(1,0);
printf("%lld\n",ans*2);
}
}
void dfs(int x){
dfn[x]=low[x]=++tot,zhan[++top]=x;
for(int i=h[x];i;i=d[i].n){
int y=d[i].b;
if(!dfn[y]){
dfs(y);
low[x]=min(low[x],low[y]);
if(low[y]==dfn[x]){
cnt++;
while(zhan[top]!=y) CP::cun(cnt,zhan[top]),top--;
CP::cun(cnt,y),top--,CP::cun(cnt,x);
}
}
else low[x]=min(low[x],dfn[y]);
}
}
inline int read(){
int num=0;
char c=getchar();
while(c<'0'||c>'9') c=getchar();
while('0'<=c&&c<='9') num=num*10+c-'0',c=getchar();
return num;
}
int main(){
freopen("sing.in","r",stdin);
freopen("sing.out","w",stdout);
scanf("%d%d%d",&n,&m,&L);
cnt=n;
for(int i=1,x,y;i<=m;i++){
x=read(),y=read();
cun(x,y),cun(y,x);
}
for(int i=1;i<=n;i++){
if(!dfn[i]) dfs(i);
}
CP::solve();
return 0;
}
标签:2024.2,int,题解,void,26,son,fa,hei,las
From: https://www.cnblogs.com/hubingshan/p/18035191