[bzoj1063][Noi2008]道路设计【树形dp】
【题目链接】
https://www.lydsy.com/JudgeOnline/problem.php?id=1063
【题解】
首先有一个结论,不便利值的最大值是级别的。
那么随便dp一下就行了。
时间复杂度
/* --------------
user Vanisher
problem bzoj-1063
----------------*/
# include <bits/stdc++.h>
# define ll long long
# define inf 0x3f3f3f3f
# define N 100010
# define K 30
using namespace std;
int read(){
int tmp=0, fh=1; char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
return tmp*fh;
}
struct node{
int data,next;
}e[N*2];
int f[N][3],cnt,head[N],place,up,n,m;
ll g[N][K][3],P,ans;
void build(int u, int v){
e[++place].data=v; e[place].next=head[u]; head[u]=place;
e[++place].data=u; e[place].next=head[v]; head[v]=place;
}
void dfs(int x, int fa){
f[x][0]=0; cnt++;
for (int ed=head[x]; ed!=0; ed=e[ed].next)
if (e[ed].data!=fa){
dfs(e[ed].data,x);
f[x][2]=min(max(f[x][2],f[e[ed].data][2]+1),max(f[x][1],f[e[ed].data][1]));
f[x][1]=min(max(f[x][1],f[e[ed].data][2]+1),max(f[x][0],f[e[ed].data][1]));
f[x][0]=max(f[x][0],f[e[ed].data][2]+1);
}
f[x][1]=min(f[x][0],f[x][1]);
f[x][2]=min(f[x][1],f[x][2]);
}
void work(int x, int fa){
for (int i=0; i<=up; i++)
g[x][i][0]=1;
for (int ed=head[x]; ed!=0; ed=e[ed].next)
if (e[ed].data!=fa){
work(e[ed].data,x);
for (int i=0; i<=up; i++){
ll f1=g[e[ed].data][i][1]+g[e[ed].data][i][0],f2;
if (i>0)
f2=(g[e[ed].data][i-1][0]+g[e[ed].data][i-1][1]+g[e[ed].data][i-1][2])%P;
else f2=0;
g[x][i][2]=(g[x][i][1]*f1+g[x][i][2]*f2)%P;
g[x][i][1]=(g[x][i][0]*f1+g[x][i][1]*f2)%P;
g[x][i][0]=(g[x][i][0]*f2)%P;
}
}
}
int main(){
n=read(), m=read(), P=read();
for (int i=1; i<=m; i++)
build(read(),read());
cnt=0;
memset(f,inf,sizeof(f));
dfs(1,0);
if (cnt!=n){
printf("-1\n-1\n");
return 0;
}
up=f[1][2];
work(1,0);
ans=(g[1][f[1][2]][0]+g[1][f[1][2]][1]+g[1][f[1][2]][2])%P;
printf("%d\n%lld\n",f[1][2],ans);
return 0;
}