2024.2.26模拟赛T1题解

题目

先建出圆方树,题目转换为数长度为 \(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;
}

posted @ 2024-02-26 21:07  hubingshan  阅读(26)  评论(0)    收藏  举报