【竞赛图】【DP】最长路径

博客分析了最长路径问题的唯一性,并通过反证法证明所有非路径点必须指向路径上的点。由此提出使用动态规划(DP)来解决这个问题。定义DP(i,j)表示i个点构成最长长度为j的路径的方案数。当i>j时,DP(i,j)=DP(j,j)*C(i-j,2),而对于i=j的情况,利用容斥原理计算DP(i,i)的值。" 54292329,5765926,Python编程入门:从零开始学Python,"['Python基础', '开发环境搭建', '编程语言类型', '数据类型', '运算符']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述


分析:

很显然,最长路径一定是唯一的。

考虑这么证明:对终点v而言,所有不在路径上的点一定指向它。
然后,对于次终的点u而言,如果它指向任意一个不在路径上的点,那么可以通过u->x->v,得到一条更长的路径,所以所有不在路径上的点也一定指向它
……
综上,除了最长路径以外,所有点都指向这条路径。

那么,就可以DP了

定义DP(i,j)DP(i,j)DP(i,j)表示:i个点的竞赛图,构成最长长度为j的路径的方案数。

显然,对于不在路径上的点,其两两之间任意连边均可,唯一要考虑的就是路径上的点。

因此,若i>j若i>ji>j,DP(i,j)=DP(j,j)∗2C(i−j,2)DP(i,j)=DP(j,j)*2^{C(i-j,2)}DP(i,j)=DP(j,j)2C(ij,2)

现在就是当i=ji=ji=j时怎么办,很显然,对于一个i个点的图,合法的jjj满足0≤j≤i0\leq j\leq i0ji,因此,可以用一下容斥:即总方案数(2(C(i,2)))(2^{(C(i,2))})(2(C(i,2))),减去所有j&lt;ij&lt;ij<i的DP值,就可以得到DP(i,i)DP(i,i)DP(i,i)的值。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define SF scanf
#define PF printf
#define MAXN 2010
using namespace std;
typedef long long ll;
ll C[MAXN][MAXN],dp[MAXN][MAXN];
ll MOD;
void prepare(int n){
	C[0][0]=1;
	for(int i=1;i<=n;i++){
		C[i][0]=1;
		for(int j=1;j<=i;j++)
			C[i][j]=(C[i-1][j-1]+C[i-1][j])%MOD;	
	}
}
ll fsp(ll x,ll y){
	ll res=1;
	while(y){
		if(y&1ll)
			res=res*x%MOD;
		x=x*x%MOD;
		y>>=1ll;	
	}
	return res;
}
int main(){
	freopen("path.in","r",stdin);
	freopen("path.out","w",stdout);
	int n;
	SF("%d%d",&n,&MOD);
	prepare(n);
	for(ll i=1;i<=n;i++){
		ll sum=0;
		for(ll j=1;j<i;j++){
			dp[i][j]=C[i-1][j-1]*dp[j][j]%MOD*fsp(2,(i-j)*(i-j-1)/2ll)%MOD;
			(sum+=dp[i][j])%=MOD;
//			PF("[%d %d :%lld]\n",i,j,dp[i][j]);
		}
		dp[i][i]=(fsp(2,i*(i-1ll)/2ll)-sum+MOD)%MOD;
//		PF("[%d %d :%lld]\n",i,i,dp[i][i]);
	}
	for(int i=1;i<=n;i++)
		PF("%lld\n",dp[n][i]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值