把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

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

点此看题面

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

最小生成树

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

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

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

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

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

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

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

代码:\(O(nm\alpha(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\n",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\n",2LL*(pw[s1]-1)*pw[s2]%X),0;//t<v求出异色能达成条件的边数和无影响的边数
}
posted @ 2021-05-10 13:24  TheLostWeak  阅读(47)  评论(0编辑  收藏  举报