Atcoder Regular Contest 093 C - Bichrome Spanning Tree
给定一张图,对图上边黑白染色,使得同时选择了两种颜色边的最小生成树边权和为X,求染色方案数。
先求出图的\(mst\)大小,然后分三类讨论:
1.\(X<mst\) 无解
2.\(X==mst\)
我们求出可以构成最小生成树的边集大小\(sumst\)。
可以发现,在这个边集里,只要不是所有边颜色相同,就一定能构造出有双色边的原图\(mst\)。边补集则可以任意染色 ;w;
方案数是\(2^{m-sumst}*(2^{sumst}-2)\)
3.\(X>mst\)
我们考虑在\(mst\)上强制加一条边对\(mst\)的贡献。
画个有点丑的树()这是某个原图的一个\(mst\)。
现在考虑强制连一条边\((3,9)\),\(w=13\)
要让其重新变成一棵树,就要在\((3,9)\)这条链上删去一条边()显然是应该删去最大的那条,即\((1,2)\),\(w=9\)
草,搞这么多不就一句话QAQ
一条边(u,v)的贡献就是\(v[i]=w[u,v]-maxw(u,v)\)
这样我们就可以用树剖+RMQ求得每条边对mst的贡献()
这样我们可以统计出对mst的贡献\(v[i]=X-mst\)的边数\(sum1\)
这样我们要使得mst边集边全部同色,sum1边集至少有一边异色,剩余的边补集任意染色。实际操作的时候我通过判断w[i]-v[i]>X-mst统计了边补集的大小sum2
方案数为\(2^{sum2}*(2^{sum1}*2-2)\)
以及第二个分类中的sumst其实是=sum1+n-1的(很显然吧x)
因为ST表我不大会写,还是写了线段树来着(
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define MAXN (int)(1e3+7)
#define MAXM (int)(2e3+14)
#define mod (int)(1e9+7)
using namespace std;
int n,m;
long long X;
struct edge
{
int x,y,z;
}a[MAXM];
struct qwq
{
int nex,to,w;
}e[MAXN<<1];
int h[MAXN],tot=0;
inline void add(int u,int v,int w)
{
e[++tot].to=v;
e[tot].nex=h[u];
e[tot].w=w;
h[u]=tot;
}
inline long long power(long long a,long long b)
{
long long answer=1,base=a;
while (b)
{
if (b&1)
{
answer*=base;
answer%=mod;
}
b>>=1;
base*=base;
base%=mod;
}
return answer;
}
inline bool cmp(edge aa,edge bb) { return aa.z<bb.z; }
int fa[MAXN];
long long mst=0;
int sum3=0;
inline void INIT1() { for (int i=1;i<=n;i++) fa[i]=i; }
inline void INIT2() { for (int i=1;i<=n;i++) fa[i]=0; }
int found(int x) { if (x==fa[x]) return x; return fa[x]=found(fa[x]); }
bool book[MAXM];
inline void MST()
{
INIT1();
sort(a+1,a+m+1,cmp);
for (int i=1,fx,fy;i<=m;i++)
{
fx=found(a[i].x); fy=found(a[i].y);
if (fx!=fy)
{
fa[fx]=fy;
add(a[i].x,a[i].y,a[i].z);
add(a[i].y,a[i].x,a[i].z);
mst+=a[i].z;
sum3++;
book[i]=1;
}
}
INIT2();
}
int ans[MAXN<<2];
#define leftson cur<<1
#define rightson cur<<1|1
#define mid ((l+r)>>1)
#define push_up ans[cur]=max(ans[leftson],ans[rightson])
int ww[MAXN];
void build(int cur,int l,int r)
{
if (l==r)
{
ans[cur]=ww[l];
return;
}
build(leftson,l,mid);
build(rightson,mid+1,r);
push_up;
}
int query(int ql,int qr,int cur,int l,int r)
{
if (ql<=l&&r<=qr) return ans[cur];
int answ=0;
if (ql<=mid) answ=query(ql,qr,leftson,l,mid);
if (qr>mid) answ=max(answ,query(ql,qr,rightson,mid+1,r));
return answ;
}
int son[MAXN],dep[MAXN],top[MAXN],siz[MAXN],id[MAXN],cnt=0;
void dfs1(int x)
{
siz[x]=1;
for (int i=h[x],y;i;i=e[i].nex)
{
y=e[i].to;
if (y==fa[x]) continue;
fa[y]=x;
dep[y]=dep[x]+1;
dfs1(y);
siz[x]+=siz[y];
if (siz[y]>siz[son[x]]) son[x]=y;
}
}
void dfs2(int x,int tp)
{
id[x]=++cnt;
top[x]=tp;
if (!son[x]) return;
dfs2(son[x],tp);
for (int i=h[x],y;i;i=e[i].nex)
{
y=e[i].to;
if (y==fa[x]) continue;
if (y==son[x]) { ww[id[son[x]]]=e[i].w; continue; }
dfs2(y,y);
ww[id[y]]=e[i].w;
}
}
inline int query_tree(int x,int y)
{
int answ=0;
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) swap(x,y);
answ=max(answ,query(id[top[x]],id[x],1,1,n));
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
return max(answ,query(id[x]+1,id[y],1,1,n));
}
int main()
{
scanf("%d%d%lld",&n,&m,&X);
for (int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
MST();
// printf("MST:%lld\n",mst);
int sum1=0,sum2=0;
if (mst>X) { printf("0\n"); return 0; }
dfs1(1);
dfs2(1,1);
build(1,1,n);
for (int i=1,W;i<=m;i++)
{
if (book[i]) continue;
W=query_tree(a[i].x,a[i].y);
// printf("W:%d %d\n",a[i].z,W);
if (a[i].z-W==X-mst) sum1++;
else if (a[i].z-W>X-mst) sum2++;
}
// printf("sum1:%d sum2:%d sum3:%d\n",sum1,sum2,sum3);
if (mst==X) printf("%lld\n",(power(2,sum2)*((power(2,sum1+sum3)-2+mod)%mod))%mod);
else printf("%lld\n",((power(2,sum2)*((2*power(2,sum1)-2+mod)%mod))%mod)%mod);
return 0;
}
/*
8 10
48
4 6 10
8 4 11
5 8 8
1 8 10
3 8 128773450
7 8 10
4 2 4
3 4 1
3 1 13
5 2 2
*/
Atcoder Regular Contest 093 C - Bichrome Spanning Tree的更多相关文章
- AtCoder Regular Contest 093
AtCoder Regular Contest 093 C - Traveling Plan 题意: 给定n个点,求出删去i号点时,按顺序从起点到一号点走到n号点最后回到起点所走的路程是多少. \(n ...
- AtCoder Regular Contest 093 E: Bichrome Spanning Tree(生成树)
Bichrome Spanning Tree 题意: 给出一个n个点,m条边的无向连通图,现在要给每条边染色,可以染成黑色或者白色. 现在要求在染色完毕后,找出一个至少包含一条黑边和一条白边的最小生成 ...
- AtCoder Regular Contest 083 E - Bichrome Tree
题目传送门:https://arc083.contest.atcoder.jp/tasks/arc083_c 题目大意: 给定一棵树,你可以给这些点任意黑白染色,并且赋上权值,现给定一个序列\(X_i ...
- Atcoder Regular Contest 093 D - Dark Horse(组合数学+状压 dp)
Atcoder 题面传送门 & 洛谷题面传送门 常规题,简单写写罢((( 首先 \(1\) 的位置是什么不重要,我们不妨钦定 \(1\) 号选手最初就处在 \(1\) 号位置,最后答案乘个 \ ...
- AtCoder Regular Contest 095
AtCoder Regular Contest 095 C - Many Medians 题意: 给出n个数,求出去掉第i个数之后所有数的中位数,保证n是偶数. \(n\le 200000\) 分析: ...
- AtCoder Regular Contest 061
AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...
- AtCoder Regular Contest 094 (ARC094) CDE题解
原文链接http://www.cnblogs.com/zhouzhendong/p/8735114.html $AtCoder\ Regular\ Contest\ 094(ARC094)\ CDE$ ...
- AtCoder Regular Contest 092
AtCoder Regular Contest 092 C - 2D Plane 2N Points 题意: 二维平面上给了\(2N\)个点,其中\(N\)个是\(A\)类点,\(N\)个是\(B\) ...
- AtCoder Regular Contest 094
AtCoder Regular Contest 094 C - Same Integers 题意: 给定\(a,b,c\)三个数,可以进行两个操作:1.把一个数+2:2.把任意两个数+1.求最少需要几 ...
- AtCoder Regular Contest 102
AtCoder Regular Contest 102 C - Triangular Relationship 题意: 给出n,k求有多少个不大于n的三元组,使其中两两数字的和都是k的倍数,数字可以重 ...
随机推荐
- EXCEL之VLOOKUP函数——查找、分组、排序
1,VLOOKUP查找 新建excel,输入测试数据,F列打乱A顺序,查找他们各自对应的学号 选中目标单元格(此处是G2),点击插入函数: 选择VLOOKUP: 我们要查找F列在A列对应的学号,所以G ...
- 免费Linux RDP,用来练习linux或者Python,还能做成远程桌面
分类:资源| 阅读:1103次阅读 goorm提供了免费的Linux容器,用它来在线练习命令行是非常不错的. 它的注册非常简单:https://ide.goorm.io/ 直接用谷歌账号登录即 ...
- 3、HTTP请求头与响应头
HTTP简介 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送 ...
- SQL语句底层执行顺序
1. SELECT 语句的完整结构 SQL92语法: SELECT ...,....,(存在聚合函数) FROM ...,...,... WHERE 多表的连接条件 AND 不包含聚合函数的过滤条件 ...
- NRF52832的FDS程序,参考非蓝牙例程修改而来(需要增加DFU的基础上只要增加如下程序即可解决)
/* Dummy configuration data. */ static configuration_t m_dummy_cfg = { .config1_on = false, .config2 ...
- 2022.07.13 vue3下pinia的简单使用及持久化
使用前说明: 当前demo使用了vue3 + vite + typescript + pinia搭建的简单项目,主要介绍了在单文件组件(sfc)基础上使用pinia的用法,懒得看api的兄弟们,来这瞅 ...
- 老系统的奇葩问题-tomcat7启动失败
好多年的tomcat7系统了 当时部署安装为了服务 直接启动 就这么简单 好多年没动过了 这次修改了些东西 需要重启 却报错了... 解决: 把服务删除 使用bat启动 成功. 原因:可能是多个 ...
- VC9.0 for Python2
python2安转包时提示: pip install xxx时,提示 Microsoft Visual C++ 9.0 is required 下载并安装: 链接:https://pan.baidu. ...
- Python内置函数:enumerate
enumerate(sequence, [start=0]) enumerate单词本身翻译为列举.枚举. 官方说明: enumerate() 函数用于将一个可遍历的数据对象(如列表.元组或字符串)组 ...
- Spring设计模式——原型模式
原型模式 原型模式(Prototype Pattern),是指原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象. 原型模式主要适用于以下场景: 类初始化消耗资源较多 使用new生成一个对象 ...