[BZOJ1063][NOI2008]道路设计
传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1063
Sol
这东西怎么长了一脸树链剖分的样子…
把公路视为轻边 发现轻边的数量是log级别的?
dp[i][j][k]表示在节点i,答案为j,这个点向下连[0,1,2]条边的方案数
直接转移即可
#include <bits/stdc++.h> using namespace std; long long dp[100005][20][4],P; int cnt,nex[200005],las[200005],Arrive[200005],fa[200005],N,M; void jt(int x,int y){ cnt++; nex[cnt]=las[x]; las[x]=cnt; Arrive[cnt]=y; } void dfs(int Now,int k,int fa){ dp[Now][k][0]=1; long long t1,t2; for (int i=las[Now];i;i=nex[i]){ int v=Arrive[i]; if (v!=fa){ dfs(v,k,Now); if (k) t1=(dp[v][k-1][0]+dp[v][k-1][1]+dp[v][k-1][2]);else t1=0;//不向这个儿子建 t2=(dp[v][k][0]+dp[v][k][1]);//向这儿子建 t1=(t1-1)%P+1; t2=(t2-1)%P+1; dp[Now][k][2]=dp[Now][k][2]*t1+dp[Now][k][1]*t2; dp[Now][k][1]=dp[Now][k][0]*t2+dp[Now][k][1]*t1; dp[Now][k][0]=dp[Now][k][0]*t1; dp[Now][k][1]=(dp[Now][k][1]-1)%P+1; dp[Now][k][0]=(dp[Now][k][0]-1)%P+1; dp[Now][k][2]=(dp[Now][k][2]-1)%P+1; } } } int Getfa(int x){ return (fa[x]==x)?x:fa[x]=Getfa(fa[x]); } int main(){ scanf("%d%d%lld",&N,&M,&P); for (int i=1;i<=N;i++) fa[i]=i; for (int i=1;i<=M;i++){ int x,y; scanf("%d%d",&x,&y); jt(x,y);jt(y,x); fa[Getfa(x)]=Getfa(y); } int x=Getfa(1); for (int i=2;i<=N;i++){ if (Getfa(i)!=x){ puts("-1"); puts("-1"); return 0; } } for (int i=0;;i++){ dfs(1,i,0); if (dp[1][i][0]||dp[1][i][1]||dp[1][i][2]){ printf("%d\n",i); printf("%lld\n",(dp[1][i][0]+dp[1][i][1]+dp[1][i][2])%P); return 0; } } }
干啥啥不行