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))

  • 相关阅读:
    POJ 3660 Cow Contest (floyd求联通关系)
    POJ 3660 Cow Contest (最短路dijkstra)
    POJ 1860 Currency Exchange (bellman-ford判负环)
    POJ 3268 Silver Cow Party (最短路dijkstra)
    POJ 1679 The Unique MST (最小生成树)
    POJ 3026 Borg Maze (最小生成树)
    HDU 4891 The Great Pan (模拟)
    HDU 4950 Monster (水题)
    URAL 2040 Palindromes and Super Abilities 2 (回文自动机)
    URAL 2037 Richness of binary words (回文子串,找规律)
  • 原文地址:https://www.cnblogs.com/autoint/p/12834215.html
Copyright © 2011-2022 走看看