zoukankan      html  css  js  c++  java
  • test20200430 最长路径

    最长路径

    在Byteland一共有(n)个城市,编号依次为(1)(n),它们之间计划修建(inom{n}{2})条单向道路,对于任意两个不同的点(i)(j),在它们之间有且仅有一条单向道路,方向要么是(i)(j),要么是(j)(i)。换句话说,这是一个(n)个点的竞赛图。

    Byteasar居住在(1)号城市,他希望从(1)号城市出发,沿着单向道路不重复地访问一些城市,使得访问的城市数尽可能多。

    请写一个程序,帮助Byteasar计算有多少种道路修建方式,使得从(1)号点出发的最长简单路径经过点数恰好为(k),由于答案可能很大,请对(P)取模输出。

    题解

    竞赛图一定存在哈密顿路径。

    对于(n)个点的竞赛图,(1)号点能作为哈密顿路径起点的充要条件是(1)能到剩余(n-1)个点。

    考虑归纳证明,(n=1,2)时显然成立。对于(ngeq 3)的情况,显然(1)能到剩余(n-1)个点是必要的,不然何谈哈密顿路径。证明充分性考虑构造,我们(1)至少能到剩余(n-1)个点导出子图的所有哈密顿路径的起点中至少一个,不然与假设矛盾。证毕。

    所以这道题要让最长路为(k)只需要让(1)能到(k)个点,其余(n-k)个点不能到即可。

    (f_n)(1)能作为哈密顿路径起点的(n)个点的竞赛图数量,(g_n=2^{inom{n}{2}})

    [f_n=g_n-sum_{i=1}^{n-1}inom{n-1}{i-1}f_ig_{n-i} ]

    最后有( ext{ans}_k=inom{n-1}{k-1}f_kg_{n-k})。时间复杂度(O(n^2))

    CO int N=2e3+10;
    int C[N][N],G[N],F[N];
    
    int main(){
    	int n=read<int>(),P=read<int>();
    	for(int i=0;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])%P;
    	}
    	for(int i=0;i<=n;++i) G[i]=fpow(2,i*(i-1)/2,P);
    	for(int i=1;i<=n;++i){
    		F[i]=G[i];
    		for(int j=1;j<=i-1;++j) F[i]=(F[i]+P-(int64)C[i-1][j-1]*F[j]%P*G[i-j]%P)%P;
    	}
    	for(int i=1;i<=n;++i){
    		int ans=(int64)C[n-1][i-1]*F[i]%P*G[n-i]%P;
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

    然后是老生常谈的生成函数优化。其实这个式子跟有标号连通无向图的一模一样。

    [F'=G'-F‘(G-1) ]

    [F'=frac{G'}{G} ]

    [F=ln Gleftrightarrow G=e^F ]

    时间复杂度(O(nlog n))

  • 相关阅读:
    VM VirtualBox安装Centos6.5
    桥接
    程序员工作心法
    策略模式-鸭子怎么飞-实例
    策略模式-用什么方式去上班呢 实例
    观察者模式-订报纸,语音呼叫系统实例
    门面(Facade)模式--医院,保安系统实例
    Promise实例的resolve方法
    Promise实例的any方法
    Promise实例的race方法
  • 原文地址:https://www.cnblogs.com/autoint/p/12834215.html
Copyright © 2011-2022 走看看