题解 [ARC093C] Bichrome Spanning Tree
赛时基本没有想这个题
所以把最水的题弃了
但是为啥 puts("0");
有 31pts 啊?
要求染色后最小的包含两种颜色的边的生成树权值为 \(x\)
先去掉这个限制把最小生成树建出来
发现此时加入一条权为 \(w\) 的边 \((u, v)\) 会使权值增加 \(w-\max\{w_i \mid e_i\in path_{u, v}\}\)
发现要找最小生成树,那么发现符合要求的树至多是最小生成树上改一条边
有了这个结论就好做了
最小生成树上的边必须同色
令 \(cost_i\) 为加入边 \(i\) 会使权值增加多少
那么按 \(cost\) 排序后若要加边 \(i\),则排名比 \(i\) 小的必须与最小生成树同色
排名比 \(i\) 大的可以随便填
特别注意最小生成树权值等于 \(x\) 时要额外贡献一个生成树上也随便填的方案数
复杂度可以 \(O(nm)\sim O(m\log m)\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define fir first
#define sec second
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline ll read() {
ll ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, m;
bool intr[N];
const ll mod=1e9+7;
ll val[N], cst[N], x, ans, sum;
struct tpl{int u, v, w;}sta[N];
struct edge{int to, next; ll val;}e[N<<1];
int head[N], dep[N], dsu[N], back[N], ecnt, top;
inline bool operator < (tpl a, tpl b) {return a.w<b.w;}
inline int find(int p) {return dsu[p]==p?p:dsu[p]=find(dsu[p]);}
inline void add(int s, int t, ll w) {e[++ecnt]={t, head[s], w}; head[s]=ecnt;}
inline ll qpow(ll a, ll b) {ll ans=1; for (; b; a=a*a%mod,b>>=1) if (b&1) ans=ans*a%mod; return ans;}
void dfs(int u, int fa) {
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (v==fa) continue;
back[v]=u;
dep[v]=dep[u]+1;
val[v]=e[i].val;
dfs(v, u);
}
}
ll qmax(int u, int v) {
ll ans=0;
while (u!=v) {
if (dep[u]<dep[v]) swap(u, v);
ans=max(ans, val[u]);
u=back[u];
}
return ans;
}
signed main()
{
// freopen("b.in", "r", stdin);
// freopen("b.out", "w", stdout);
n=read(); m=read(); x=read();
memset(head, -1, sizeof(head));
for (int i=1; i<=n; ++i) dsu[i]=i;
for (int i=1,u,v,w; i<=m; ++i) {
u=read(); v=read(); w=read();
sta[i]={u, v, w};
}
sort(sta+1, sta+m+1);
for (int i=1,s,t; i<=m; ++i) if ((s=find(sta[i].u))!=(t=find(sta[i].v))) {
dsu[s]=t; sum+=sta[i].w; intr[i]=1;
add(sta[i].u, sta[i].v, sta[i].w);
add(sta[i].v, sta[i].u, sta[i].w);
}
dep[1]=1; dfs(1, 0);
if (sum==x) ans=(ans+(qpow(2, n-1)-2)*qpow(2, m-n+1))%mod;
for (int i=1; i<=m; ++i) if (!intr[i]) cst[++top]=sta[i].w-qmax(sta[i].u, sta[i].v);
sort(cst+1, cst+top+1);
for (int i=1; i<=top; ++i) if (sum+cst[i]==x) ans=(ans+qpow(2, top-i+1))%mod;
printf("%lld\n", (ans%mod+mod)%mod);
return 0;
}