• 2022牛客多校#6 C. Forest


    题目大意

    给定 n ( 1 ≤ n ≤ 16 ) n(1 \leq n \leq 16) n(1n16) 个点 m ( 0 ≤ m ≤ 100 ) m(0 \leq m \leq 100) m(0m100) 条正边权的无向简单图,求每个生成子图的最小生成森林的权值和,答案对 998244353 998244353 998244353 取模。

    定义点集 V V V ,边集 E E E 的图 G G G 的最小生成森林为:

    • 最小生成森林的边集 S ⊆ E S \subseteq E SE
    • 任意两个节点的连通性不变
    • S S S 为满足以上条件的最小权值。

    G G G 的生成子图为具有点集 V V V 和边集为 E E E 的子集所构成的图。

    题解

    类似题目 P6789

    单独考虑按边权值从小到大枚举每条边的贡献,边权值第 i i i 小的边为 e i = ( u i , v i , w i ) e_i=(u_i,v_i,w_i) ei=(ui,vi,wi)
    由于求所有方案的总权值和,因此边权值相同的边任意排序后不影响结果。

    定理:

    • 一条边在生成子图的最小生成森林中,当且仅当该子图中其他权值更小的点不能使得两端联通。

    对于边 e i = ( u i , v i , w i ) e_i=(u_i,v_i,w_i) ei=(ui,vi,wi) ,求有多少生成子图的最小生成森林包含该边。

    边编号在 [ i + 1 , m ] [i+1,m] [i+1,m] 范围内的边,不影响 e i e_i ei 的选取,方案数为 2 m − 1 − i 2^{m-1-i} 2m1i

    考虑边编号在 [ 1 , i − 1 ] [1,i-1] [1i1] 范围内的边。
    设边编号在 [ 1 , i − 1 ] [1,i-1] [1,i1] 范围内,且端点均在点集 S S S 内的边数为 C n t i − 1 ( S ) Cnt_{i-1}(S) Cnti1(S) ,有转移式
    C n t i ( S ) = [ u i ∈ S & v i ∈ S ] + C n t i − 1 ( S ) Cnt_{i}(S)=[u_i\in S\&v_i \in S]+Cnt_{i-1}(S) Cnti(S)=[uiS&viS]+Cnti1(S)

    设边编号在 [ 1 , i − 1 ] [1,i-1] [1,i1] 范围的边构成连通块 S S S ,则

    1. 两端在 S S S 外的边,可以任意选取。方案数为 2 C n t i − 1 ( V − S ) 2^{Cnt_{i-1}(V-S)} 2Cnti1(VS)
    2. 只有一段在 S S S 内的边,均不能选取,否则连通块就不是 S S S 了。方案数为 1 1 1
    3. 两端都在 S S S 内的边,有一部分需要被选取使得构成连通块 S S S 。设方案数为 f i − 1 ( S ) f_{i-1}(S) fi1(S)

    考虑计算 f i − 1 ( S ) f_{i-1}(S) fi1(S) ,等于总方案数-至少有两个连通块的方案数。
    可以直接计算,枚举 S S S 中包含编号最小的节点的连通块 T T T ,则剩余部分为 S − T S-T ST ,有
    f i − 1 ( S ) = 2 C n t i − 1 ( S ) − ∑ T ⊂ S , l o w b i t ( S ) = l o w b i t ( T ) f i − 1 ( T ) ⋅ 2 C n t i − 1 ( S − T ) f_{i-1}(S)=2^{Cnt_{i-1}(S)}-\sum_{T \subset S,lowbit(S)=lowbit(T)}{f_{i-1}(T)\cdot 2^{Cnt_{i-1}(S-T)}} fi1(S)=2Cnti1(S)TS,lowbit(S)=lowbit(T)fi1(T)2Cnti1(ST)

    上式的复杂度为 O ( 3 n ) O(3^n) O(3n) ,搭配枚举 m m m ,复杂度为 O ( 3 n m ) O(3^n m) O(3nm) ,约 4e9 ,勉强可以计算出结果。

    e i e_i ei 的贡献为
    W i = w i × ( 2 m − 1 − 2 m − i − 1 × ∑ S ⊆ V , u i ∈ S , v i ∈ S 2 C n t i − 1 ( V − S ) f i − 1 ( S ) ) W_i=w_i\times(2^{m-1}-2^{m-i-1} \times \sum_{S\subseteq V,u_i \in S,v_i \in S}{2^{Cnt_{i-1}(V-S)}f_{i-1}(S)}) Wi=wi×(2m12mi1×SV,uiS,viS2Cnti1(VS)fi1(S))

    也可以考虑加入 e i e_i ei 边,从 f i − 1 ( S ) f_{i-1}(S) fi1(S) 递推到 f i ( S ) f_{i}(S) fi(S) ,有
    f i ( S ) = { 2 f i − 1 ( S ) + ∑ T ⊂ S , u i ∉ T , v i ∉ T f i − 1 ( S − T − v i ) ⋅ f i − 1 ( T + u i ) u i ∈ S , v i ∈ S f i − 1 ( S ) o t h e r s f_i(S)=

    {2fi1(S)+TS,uiT,viTfi1(STvi)fi1(T+ui)uiS,viSfi1(S)others" role="presentation" style="position: relative;">{2fi1(S)+TS,uiT,viTfi1(STvi)fi1(T+ui)uiS,viSfi1(S)others
    fi(S)={2fi1(S)+TS,ui/T,vi/Tfi1(STvi)fi1(T+ui)fi1(S)uiS,viSothers

    总复杂度 O ( m ⋅ 3 n − 2 ) O(m\cdot 3^{n-2}) O(m3n2) ,约4e8。

    参考代码

    来自杭电6队

    #include
    #define ll long long
    using namespace std;
    const int N=20;
    const int mod=998244353;
    struct node{
    	int u,v,s;
    };
    vector<node>w;
    bool operator<(const node&x,const node&y){
    	return x.s<y.s;
    }
    int n;
    int a[N][N],f[1<<N],g[1<<N],fac[1000],sum[1<<N];
    int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
    int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
    int mul(int x,int y){return (ll)x*y%mod;}
    int main(){
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++){
    		for (int j=1;j<=n;j++) scanf("%d",&a[i][j]);
    	}
    	for (int i=1;i<=n;i++) 
    		for (int j=i+1;j<=n;j++)if (a[i][j]){
    			node t; t.u=i; t.v=j; t.s=a[i][j];
    			w.push_back(t);
    		}
    	sort(w.begin(),w.end());
    	for (int i=1;i<=n;i++) f[1<<(i-1)]=1;
    	fac[0]=1;
    	for (int i=1;i<=500;i++) fac[i]=mul(fac[i-1],2);
    	int m=(1<<n)-1,ans=0;
    	for (int i=0;i<w.size();i++){
    		int u=w[i].u,v=w[i].v; u--;v--;
    		int t=(1<<n)-1;
    		t^=(1<<u);
    		t^=(1<<v);
    		int s=fac[i];
    		for (int j=0;j<(1<<n);j++) if ((j&(1<<u))&&(j&(1<<v))) s=dec(s,mul(f[j],fac[sum[m^j]]));
    		ans=add(ans,mul(mul(s,w[i].s),fac[(int)w.size()-i-1]));
    		for (int j=t;~j;j=(j?((j-1)&t):-1))
    			for (int k=j;~k;k=(k?((k-1)&j):-1)) {
    			g[j|(1<<u)|(1<<v)]=add(g[j|(1<<u)|(1<<v)],mul(f[(j^k)|(1<<u)],f[k|(1<<v)]));
    			}
    		for (int j=0;j<=m;j++){
    		if ((j&(1<<u))&&(j&(1<<v))) f[j]=mul(f[j],2);
    		f[j]=add(f[j],g[j]); g[j]=0;
    		}
    		for (int j=0;j<(1<<n)-1;j++) if ((j&(1<<u))&&(j&(1<<v))) sum[j]++; 
    	}
    	printf("%d\n",ans);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
  • 相关阅读:
    多元线性回归详解
    BHQ-2 NHS,916753-62-3作为各种荧光共振能量转移DNA检测探针中淬灭部分
    选择结构——分段函数
    [修改Linux下ssh端口号]解决无法修改sshd_config无法修改
    网上流量卡这么便宜,线上申请的流量卡有虚标吗
    试用程序实现不使用缓存字节数组的方法复制C盘根目录下的a,jpg到E盘下的a.jpg
    1-5-10 快恢在数字化安全生产平台 DPS 中的设计与落地
    高级管理学:大题
    设计模式学习笔记(二十二)解释器模式及其实现
    springboot 数据翻译:支持枚举翻译、字典翻译、外键翻译、级联翻译、方法翻译
  • 原文地址:https://blog.csdn.net/xin_jun/article/details/126210190