• 【AT3980】[ARC093C] Bichrome Spanning Tree(MST)


    点此看题面

    • 给定一张(n)个点(m)条边的图,求有多少种给边黑白染色的方案,使得同时包含黑白边的最小生成树权值恰好为(v)
    • (nle10^3,mle2 imes10^3)

    最小生成树

    考虑先随便找出一棵最小生成树,设其权值为(t)

    显然若(t>v)必然无解。

    如果(t=v),那么原图中任何一棵最小生成树都是符合条件的。因此我们求出可能在最小生成树中的总边数(s),则只要这(s)条边不完全同色即可,因此答案为((2^s-2) imes 2^{m-s})

    关键还是在于(t<v),显然这棵最小生成树上的所有边必然同色,否则它就成了同时包含黑白边的最小生成树。

    根据最小生成树的性质,我们至多加入一条异色边去替换最小生成树中的一条边,因为用更多的边去替换必然权值更大。

    那么我们就枚举最小生成树外的每条边,如果加入它权值仍然小于(v)则它也得同色,如果等于(v)那么它填成异色可以达成条件(记这种边数为(s1)),而如果大于(v)那么它填什么颜色都不会影响到最小生成树权值(记这种边数为(s2))。

    由于最小生成树有两种颜色,而能够填成异色达成条件的边不能全为同色,因此答案就是(2 imes(2^{s1}-1) imes2^{s2})

    代码:(O(nmalpha(n)))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 1000
    #define M 2000
    #define X 1000000007
    #define LL long long
    using namespace std;
    int n,m,pw[M+5],used[M+5];LL v;
    struct edge {int x,y,v,u;I bool operator < (Con edge& o) Con {return v<o.v;}}e[M+5];
    int f[N+5];I int fa(CI x) {return f[x]^x?f[x]=fa(f[x]):x;}//并查集
    I LL MST(CI id)//强制选择id时的最小生成树
    {
    	RI i,fx,fy;LL t=0;for(i=1;i<=n;++i) f[i]=i;id&&(t=e[id].v,f[e[id].y]=e[id].x);//强制选择id
    	for(i=1;i<=m;++i) (fx=fa(e[i].x))^(fy=fa(e[i].y))&&(t+=e[i].v,f[fy]=fx,e[i].u=1);return t;//最小生成树
    }
    int main()
    {
    	RI i;for(scanf("%d%d%lld",&n,&m,&v),pw[0]=i=1;i<=m;++i)
    		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].v),pw[i]=2LL*pw[i-1]%X;sort(e+1,e+m+1);//把边按权值排序贪心
    	RI s1=0,s2=0;LL t=MST(0);for(i=1;i<=m;++i) used[i]=e[i].u;if(t>v) return puts("0"),0;//t>v显然无解
    	if(t==v) {for(i=1;i<=m;++i) MST(i)==v&&++s1;return printf("%d
    ",1LL*(pw[s1]-2)*pw[m-s1]%X),0;}//t=v求出可能在最小生成树上的边数
    	for(i=1;i<=m;++i) !e[i].u&&((t=MST(i))==v?++s1:t>v&&++s2);return printf("%d
    ",2LL*(pw[s1]-1)*pw[s2]%X),0;//t<v求出异色能达成条件的边数和无影响的边数
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    ThreadLocal的原理和使用场景
    sleep wait yield join方法的区别
    GC如何判断对象可以被回收
    双亲委派
    ConcurrentHashMap原理,jdk7和jdk8版本
    hashCode和equals
    接口和抽象类区别
    为什么局部内部类和匿名内部类只能访问局部final变量
    【GAN】基础GAN代码解析
    TF相关codna常用命令整理
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/AT3980.html
Copyright © 2020-2023  润新知