BZOJ 1063 道路设计NOI2008
http://www.lydsy.com/JudgeOnline/problem.php?id=1063
题意:给你一棵树,也有可能是不连通的,把树分成几个链,求每个点到根经过的最大链数最小,而且要输出方案数。
思路:考虑dp,f[i][j]代表第i个节点,最大链数是j,那么有
f[i][j][0]代表已经向子树连接了0个链
f[i][j][1]代表已经向子树连接了1个链
f[i][j][2]代表已经向子树连接了2个链
这样转移就是
f1=f[pur][b][0]+f[pur][b][1]
f2=f[pur][b-1][0]+f[pur][b-1][1]+f[pur][b-1][2]
f[x][b][2]=f2*f[x][b][2]+f1*f[x][b][1]
f[x][b][1]=f1*f[x][b][0]+f2*f[x][b][1]
f[x][b][0]=f[x][b][0]*f2
pur代表x的儿子
1 #include<cstdio> 2 #include<cmath> 3 #include<iostream> 4 #include<cstring> 5 #include<algorithm> 6 #define ll long long 7 ll Mod; 8 int first[200005],next[200005],go[200005],tot; 9 int n,m,fa[200005]; 10 ll f[100005][12][3]; 11 int read(){ 12 int t=0,f=1;char ch=getchar(); 13 while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();} 14 while ('0'<=ch&&ch<='9') {t=t*10+ch-'0';ch=getchar();} 15 return t*f; 16 } 17 void insert(int x,int y){ 18 tot++; 19 go[tot]=y; 20 next[tot]=first[x]; 21 first[x]=tot; 22 } 23 void add(int x,int y){ 24 insert(x,y);insert(y,x); 25 } 26 int find(int x){ 27 if (fa[x]==x) return x;else return fa[x]=find(fa[x]); 28 } 29 ll get(ll x){ 30 if (x%Mod!=0) return x%Mod; 31 if (x!=0) return Mod; 32 return 0; 33 } 34 void dfs(int x,int b,int fa){ 35 f[x][b][0]=1; 36 f[x][b][1]=0; 37 f[x][b][2]=0; 38 for (int i=first[x];i;i=next[i]){ 39 int pur=go[i]; 40 if (pur==fa) continue; 41 dfs(pur,b,x); 42 ll f1=(f[pur][b][0]+f[pur][b][1]); 43 ll f2; 44 if (b) f2=f[pur][b-1][0]+f[pur][b-1][1]+f[pur][b-1][2];else f2=0; 45 f[x][b][2]=get(f2*f[x][b][2]+f1*f[x][b][1]); 46 f[x][b][1]=get(f1*f[x][b][0]+f2*f[x][b][1]); 47 f[x][b][0]=get(f[x][b][0]*f2); 48 } 49 } 50 int main(){ 51 n=read();m=read();Mod=read(); 52 for (int i=1;i<=n;i++) fa[i]=i; 53 for (int i=1;i<=m;i++){ 54 int x=read(),y=read(); 55 add(x,y); 56 int p=find(x),q=find(y); 57 if (p!=q) fa[q]=p; 58 } 59 for (int i=2;i<=n;i++) 60 if (find(i)!=find(1)){printf("-1\n-1\n");return 0;} 61 for (int i=0;;i++){ 62 dfs(1,i,0); 63 if (f[1][i][0]+f[1][i][1]+f[1][i][2]){ 64 printf("%d\n",i); 65 printf("%lld\n",((f[1][i][0]+f[1][i][1])%Mod+f[1][i][2])%Mod); 66 return 0; 67 } 68 } 69 }