[bzoj1063][Noi2008]道路设计【树形dp】

【题目链接】
  https://www.lydsy.com/JudgeOnline/problem.php?id=1063
【题解】
  首先有一个结论,不便利值的最大值是logN级别的。
  那么随便dp一下就行了。
  时间复杂度O(NlogN)
  

/* --------------
    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;
}
posted @ 2018-04-01 20:44  Vanisher  阅读(109)  评论(0编辑  收藏  举报