【BZOJ1063】【NOI2008】道路设计(动态规划)

【BZOJ1063】【NOI2008】道路设计(动态规划)

题面

BZOJ

题解

发现每个点最多只能被修一次等价于每个点最多只能和两条铁路相邻
考虑一个(dp)
(f[i][0/1/2])表示以(i)为根,当前点与他的儿子已经有(0/1/2)条铁路相邻的方案数
转移也很简单,考虑每个儿子,枚举是修还是不修就行了
这样的复杂度是(O(n))

这样的前提是不需要计算答案的方案数,我们可以很容易想出来
现在考虑如何计算方案数。
考虑一下答案的范围,如果我们把这棵树进行树链剖分
重链视为修铁路,那么任意一个点跳轻边的次数不会超过(log)
所以,答案一定不会超过(log)
这样子在做的时候把答案限制也加上就好了
(f[i][j][k])表示以(i)为根的子树,答案为(j)
当前点与(k)条铁路相邻的方案数,其中(kin{0,1,2})
转移和前面没有太多的区别,只需要注意一下答案那一位的变化就行了
时间复杂度(O(nlogn))
注意一下这道题目要怎么取模

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 100100
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
struct Line{int v,next;}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
int n,m,MOD;
int f[MAX][20][3];
void add(int &x,int y){x+=y;if(x>MOD)x-=MOD;}
int mod(ll x){if(x!=0&&x%MOD==0)return MOD;return x%MOD;}
void dfs(int u,int ff)
{
	for(int i=0;i<20;++i)f[u][i][0]=1;--n;
	for(int i=h[u];i;i=e[i].next)
	{
		int v=e[i].v;if(v==ff)continue;
		dfs(v,u);
		for(int ans=0;ans<19;++ans)
		{
			int f0=0,f1=0;
			if(ans)f0=mod(1ll*f[v][ans-1][0]+f[v][ans-1][1]+f[v][ans-1][2]);
			f1=mod(1ll*f[v][ans][0]+f[v][ans][1]);
			f[u][ans][2]=mod(1ll*f[u][ans][2]*f0+1ll*f[u][ans][1]*f1);
			f[u][ans][1]=mod(1ll*f[u][ans][1]*f0+1ll*f[u][ans][0]*f1);
			f[u][ans][0]=mod(1ll*f[u][ans][0]*f0);
		}
	}
}
int main()
{
	n=read();m=read();MOD=read();
	for(int i=1;i<=m;++i)
	{
		int u=read(),v=read();
		Add(u,v);Add(v,u);
	}
	dfs(1,0);
	if(n){puts("-1");puts("-1");return 0;}
	int ans=1e9,tot=0;
	for(int i=0;i<20;++i)
		if(f[1][i][0]||f[1][i][1]||f[1][i][2]){ans=i;break;}
	tot=mod(1ll*f[1][ans][0]+f[1][ans][1]+f[1][ans][2])%MOD;
	printf("%d
%d
",ans,tot);
	return 0;
}

原文地址:https://www.cnblogs.com/cjyyb/p/9155943.html