Description

现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生成树可能很多,所以你只需要输出方案数对31011的模就可以了。
Input

第一行包含两个数,n和m,其中1<=n<=100; 1<=m<=1000; 表示该无向图的节点数和边数。每个节点用1~n的整数编号。接下来的m行,每行包含两个整数:a, b, c,表示节点a, b之间的边的权值为c,其中1<=c<=1,000,000,000。数据保证不会出现自回边和重边。注意:具有相同权值的边不会超过10条。
Output

输出不同的最小生成树有多少个。你只需要输出数量对31011的模就可以了。
Sample Input
4 6
1 2 1
1 3 1
1 4 1
2 3 2
2 4 1
3 4 1

Sample Output
8

网上的题解基本上没有证明(或许有,但是我没看见,然后懒得找了)

两个最小生成树的权值相同的边作用相同(连通情况)

我们可以用反证法

假设有两个最小生成树的权值相同的边作用不同,那么把最小的作用不同的权值找出来

然后我们把他们的连通情况合并(去环),需要的边肯定会变多,而且一定可以做到,相当于我们用多出来的边代替了权值比它大的边,那这与前面说的这是最小生成树矛盾

例:假设权值为1的边在一棵最小生成树里造成连通情况是(1,2)(3,4),在另一棵最小生成树里造成的连通情况是(1,4)(2,3)

那我们可以合并它们用权值为1的边做到(1,2,3,4),来替换一条权值大于1的边,得到一颗权值更小的树

证毕.

所以我们记录每种权值的边所造成的连通情况记录下来,每个权值做一遍,乘起来就是答案(注意判断无解的情况)

 const
maxn=;
maxm=;
h=;
var
ans,n,m,l:longint;
u,v,w:array[..maxm]of longint;
a:array[..,..]of longint; procedure swap(var x,y:longint);
var
t:longint;
begin
t:=x;x:=y;y:=t;
end; procedure sort(l,r:longint);
var
i,j,y:longint;
begin
i:=l;
j:=r;
y:=w[(l+r)>>];
repeat
while w[i]<y do
inc(i);
while w[j]>y do
dec(j);
if i<=j then
begin
swap(u[i],u[j]);
swap(v[i],v[j]);
swap(w[i],w[j]);
inc(i);
dec(j);
end;
until i>j;
if i<r then sort(i,r);
if j>l then sort(l,j);
end; function bit(x:longint):longint;
begin
if x= then exit();
exit(bit(x-(x and -x))+);
end; procedure init;
var
i,k:longint;
begin
read(n,m);
for i:= to m do
read(u[i],v[i],w[i]);
sort(,m);
for i:= to do
begin
k:=bit(i);
inc(a[k,]);
a[k,a[k,]]:=i;
end;
end; var
f,f2,vis:array[..maxn]of longint;
xu:array[..maxm]of longint;
time:longint; function find(x:longint):longint;
begin
if vis[x]<>time then
begin
f[x]:=f2[x];
vis[x]:=time;
end;
if f[x]=x then exit(x);
f[x]:=find(f[x]);
exit(f[x]);
end; function find2(x:longint):longint;
begin
if f2[x]=x then exit(x);
f2[x]:=find2(f2[x]);
exit(f2[x]);
end; function flag(x:longint):boolean;
var
i:longint;
begin
i:=;
while x> do
begin
inc(i);
if x and = then
begin
if find(u[l+i])=find(v[l+i]) then exit(false);
if (f[u[l+i]]<>f[v[l+i]])and(find2(u[l+i])=find2(v[l+i])) then exit(false);
f[f[u[l+i]]]:=f[v[l+i]];
end;
x:=x>>;
end;
exit(true);
end; procedure work;
var
i,j,s,last:longint;
begin
ans:=;
for i:= to n do
f2[i]:=i;
for i:= to m do
begin
if w[i]=w[i-] then xu[i]:=xu[i-];
if find2(u[i])<>find2(v[i]) then
begin
inc(xu[i]);
f2[f2[u[i]]]:=f2[v[i]];
end;
end;
for i:= to n- do
if find2(i)<>find2(i+) then ans:=;
for i:= to n do
f2[i]:=i;
l:=;
last:=;
for i:= to m do
if w[i]<>w[i+] then
begin
s:=;
while last<l do
begin
inc(last);
f2[find2(u[last])]:=find2(v[last]);
end;
for j:= to a[xu[i],] do
begin
if a[xu[i],j]>=<<(i-l) then break;
inc(time);
if flag(a[xu[i],j]) then inc(s);
end;
l:=i;
ans:=ans*s mod h;
end;
write(ans);
end; begin
init;
work;
end.

1016: [JSOI2008]最小生成树计数 - BZOJ的更多相关文章

  1. BZOJ 1016: [JSOI2008]最小生成树计数( kruskal + dfs )

    不同最小生成树中权值相同的边数量是一定的, 而且他们对连通性的贡献是一样的.对权值相同的边放在一起(至多10), 暴搜他们有多少种方案, 然后乘法原理. ----------------------- ...

  2. 【BZOJ 1016】 1016: [JSOI2008]最小生成树计数 (DFS|矩阵树定理)

    1016: [JSOI2008]最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树 ...

  3. 1016: [JSOI2008]最小生成树计数

    1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 6200  Solved: 2518[Submit][St ...

  4. [BZOJ]1016 JSOI2008 最小生成树计数

    最小生成树计数 题目描述 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同 ...

  5. 【BZOJ】1016: [JSOI2008]最小生成树计数 深搜+并查集

    最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小 ...

  6. [BZOJ 1016] [JSOI2008] 最小生成树计数 【DFS】

    题目链接:BZOJ - 1016 题目分析 最小生成树的两个性质: 同一个图的最小生成树,满足: 1)同一种权值的边的个数相等 2)用Kruscal按照从小到大,处理完某一种权值的所有边后,图的连通性 ...

  7. 【BZOJ】1016: [JSOI2008]最小生成树计数(kruskal+特殊的技巧)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1016 想也想不到QAQ 首先想不到的是:题目有说,具有相同权值的边不会超过10条. 其次:老是去想组 ...

  8. BZOJ.1016.[JSOI2008]最小生成树计数(Matrix Tree定理 Kruskal)

    题目链接 最小生成树有两个性质: 1.在不同的MST中某种权值的边出现的次数是一定的. 2.在不同的MST中,连接完某种权值的边后,形成的连通块的状态是一样的. \(Solution1\) 由这两个性 ...

  9. bzoj 1016 [JSOI2008]最小生成树计数——matrix tree(相同权值的边为阶段缩点)(码力)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1016 就是缩点,每次相同权值的边构成的联通块求一下matrix tree.注意gauss里的 ...

随机推荐

  1. Sharepoint2010之父子表实现

    在Sharepoint的实际运用中会经常使用到父子表来建立2个表之间的关系.通常父表为表头,存储公共的数据项目,子表存储细分的项目. 例如通过下面2个表实现图书借阅功能,表1为图书的基础信息,表2为图 ...

  2. CSS中link和@import的区别是:

    Link属于html标签,而@import是CSS中提供的 在页面加载的时候,link会同时被加载,而@import引用的CSS会在页面加载完成后才会加载引用的CSS @import只有在ie5以上才 ...

  3. spark集成hive遭遇mysql check失败的问题

    问题: spark集成hive,启动spark-shell或者spark-sql的时候,报错: INFO MetaStoreDirectSql: MySQL check failed, assumin ...

  4. TSQL基础(四) - 日期处理

    日期类型-DateTime DateTime是sql中最常用的日期类型. 存储大小为:8个字节: 日期范围:1753-01-01到9999-12-31: 精确度:3.33毫秒: 常用的日期函数 Get ...

  5. 如何同时启动多个Tomcat服务器

    1.使用压缩版的tomcat不能使用安装版的. 2.第一个tomcat的配置不变. 3.增加环境变量CATALINA_HOME2,值为新的tomcat的地址:增加环境变量CATALINA_BASE2, ...

  6. JAVA实现上传下载共享文件

    1.上传下载共享文件需要用到jcifs,先下载相关JAR包(开源项目的源码,demo,文挡.API应有尽有) https://jcifs.samba.org/src/

  7. C#程序员整理的Unity 3D笔记(十五):Unity 3D UI控件至尊–NGUI

    目前,UGUI问世不过半年(其随着Unity 4.6发布问世),而市面上商用的产品,UI控件的至尊为NGUI:影响力和广度(可搜索公司招聘Unity 3D,常常能看到对NGUI关键词). NGUI虽然 ...

  8. Stored Procedures with Multiple Result Sets

    Stored Procedures with Multiple Result Sets https://msdn.microsoft.com/en-us/data/jj691402.aspx

  9. (转)实战Memcached缓存系统(6)Memcached CAS的多线程程序实例

    1. 源程序 package com.sinosuperman.memcached; import java.io.IOException; import java.net.InetSocketAdd ...

  10. ajax — get? or post?

    ajax - get? or post? 与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用. 然而,在以下情况中,请使用 POST 请求: 无法使用缓存文件(更新服务器上的文件或数据 ...