【Kruskal+dfs】BZOJ1016- [JSOI2008]最小生成树计数
【题目大意】
现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树。
【思路】
拖欠了三个月整(?)的题目,搞出来弄掉了……本年度写的时候姿势最丑的程序,完全不知道自己在搞些什么,晕乎乎的,算了。
首先,MST具有以下性质:
1.对于同一张无向加权图G,它的最小生成树中长度为L的边长度一定。
2.MST用Kruskal做,处理完长度<=x,此时图的连通性是确定的。
我其实没有读懂第二句话是什么意思,总之大概理解一下,然后乱搞!怎么搞呢。
先按照普通的Kruskal,按照边长排序,然后排序,然后记录下排序为i的长度有几条边numss,下标为nstart到nend。然后弄出一组MST的解。这个不需要单独搞,只需要在记录边的条数的时候一边操作一边进行Kruskal(详细见程序)。
注意一下做完之后有可能进行合并操作的次数,也就是选的边是小于N-1的,也就是没有生成树,特判一下。
接着dfs,枚举每条边取numss个。由于题目条件相同长度的边至多10个,只需暴搜索2^10。每次就判断一下当前这条边左右两边是否已经在同一个并查集里面了,如果不在就可以尝试取这条边合并两段,dfs;或者这条边不取,直接dfs下去。
嗯,然后乘法原理就好了!
什么乱七八糟的题解……
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define mod 31011
using namespace std;
const int MAXN=+;
struct node
{
int fr,to,len;
bool operator < (const node &x) const
{
return len<x.len;
}
}edge[MAXN];
int num[MAXN],numss=-,nstart[MAXN],nend[MAXN];//num[i]长度排序为i的边长需要取多少个,nstart/nend表示长度排序为i的边长排序为几到几
int n,m,pa[MAXN],tot=,ans,tmpans;
int find(int x){return (pa[x]==x?x:find(pa[x]));} void dfs(int now,int r,int total,int num)
{
if (num>total) return;
if (now>r)
{
if (num==total) tmpans++;
return;
}
int u=edge[now].fr,v=edge[now].to;
int fa=find(u),fb=find(v);
if (fa!=fb)
{
pa[fa]=fb;
dfs(now+,r,total,num+);
pa[fa]=fa;
}
dfs(now+,r,total,num);
} void init()
{
scanf("%d%d",&n,&m);
for (int i=;i<m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
edge[i]=(node){a,b,c};
}
sort(edge,edge+m);
} void kruskal()
{
memset(num,,sizeof(num));
for (int i=;i<=n;i++) pa[i]=i;
for (int i=;i<m;i++)
{
if (i== || edge[i].len!=edge[i-].len)
{
if (i!=) nend[numss]=i-;
nstart[++numss]=i;
}
int fa=find(edge[i].fr),fb=find(edge[i].to);
if (fa!=fb)
{
pa[fa]=fb;
num[numss]++;
tot++;
}
}
nend[numss]=m-;
} void solve()
{
if (tot<n-) puts("");
else
{
ans=;
for (int i=;i<=n;i++) pa[i]=i;
for (int i=;i<=numss;i++)
{
tmpans=;
dfs(nstart[i],nend[i],num[i],);
ans=(ans*tmpans)%mod;
for (int j=nstart[i];j<=nend[i];j++)
{
int u=edge[j].fr,v=edge[j].to;
int fa=find(u),fb=find(v);
if (fa!=fb) pa[fa]=fb;
}
}
printf("%d",ans);
}
} int main()
{
freopen("bzoj_1016.in","r",stdin);
freopen("bzoj_1016.out","w",stdout);
init();
kruskal();
solve();
return ;
}
【Kruskal+dfs】BZOJ1016- [JSOI2008]最小生成树计数的更多相关文章
- bzoj1016: [JSOI2008]最小生成树计数(kruskal+dfs)
1016: [JSOI2008]最小生成树计数 题目:传送门 题解: 神题神题%%% 据说最小生成树有两个神奇的定理: 1.权值相等的边在不同方案数中边数相等 就是说如果一种方案中权值为1的边有n条 ...
- bzoj1016 [JSOI2008]最小生成树计数
1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3517 Solved: 1396[Submit][St ...
- bzoj1016: [JSOI2008]最小生成树计数(kruskal+dfs)
一直以为这题要martix-tree,实际上因为有相同权值的边不大于10条于是dfs就好了... 先用kruskal求出每种权值的边要选的次数num,然后对于每种权值的边2^num暴搜一下选择的情况算 ...
- [BZOJ1016] [JSOI2008] 最小生成树计数 (Kruskal)
Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...
- BZOJ1016:[JSOI2008]最小生成树计数(最小生成树,DFS)
Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...
- [bzoj1016][JSOI2008]最小生成树计数 (Kruskal + Matrix Tree 定理)
Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...
- bzoj1016 [JSOI2008]最小生成树计数——Kruskal+矩阵树定理
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1016 从 Kruskal 算法的过程来考虑产生多种方案的原因,就是边权相同的边有一样的功能, ...
- 【Matrix-tree定理】【并查集】【kruscal算法】bzoj1016 [JSOI2008]最小生成树计数
题意:求一个图的最小生成树个数. 矩阵树定理:一张无向图的生成树个数 = (度数矩阵 - 邻接矩阵)的任意一个n-1主子式的值. 度数矩阵除了对角线上D[i][i]为i的度数(不计自环)外,其他位置是 ...
- [BZOJ1016][JSOI2008]最小生成树计数(结论题)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1016 分析: 首先有个性质:如果边集E.E'都可以表示一个图G的最小生成树(当然E和E ...
随机推荐
- 更改控件中DrawableLeft图片的大小,图片与文字的距离
Drawable drawable=getResources().getDrawable(R.drawable.xx); //获取图片 drawable.setBounds(left, top, ri ...
- SpringCloud Feign重试详解
摘要: 今天在生产环境发生了数据库进程卡死的现象,除了sql因为全量更新,没加索引的原因,最主要还是我们的接口的服务器端接口出现问题了.忽视了更新接口的幂等性,以及调用方feign client的重试 ...
- 在 kernel 下打出 有帶參數的log。 怪異現象與解決方式。
code battery_log(BAT_LOG_CRTI, "youchihwang abc10010 xxxaaa8-2\r\n"); battery_log(BAT_LOG_ ...
- 64_k1
KoboDeluxe-0.5.1-22.fc26.x86_64.rpm 13-Feb-2017 22:11 1626454 k3b-17.04.1-1.fc26.x86_64.rpm 25-May-2 ...
- OWASP SSL 高级审查工具
http://www.linuxidc.com/Linux/2016-03/129164.htm InfoWorld 在部署.运营和保障网络安全领域精选出了年度开源工具获奖者. 最佳开源网络和安全软件 ...
- 33.Search in Rotated Sorted Array---二分变形---《剑指offer》面试题8
题目链接 题目大意:在一个旋转数组中,判断给定的target是否存在于该旋转数组中.数组中没有重复数值.例子如下: 法一:二分.确定中间元素之后,就要判断下一步是遍历左数组还是遍历右数组.如果左数组有 ...
- tornado write render redirect IP
write 用法( self.flush() ) render (跳转指定网页)用法 redirect(跳转指定路由)用法 self.request.remote_ip 显示用户 IP 地址 less ...
- Microsoft .NET Native
首页: https://msdn.microsoft.com/en-US/vstudio/dotnetnative
- 调用微信JS-SDK接口上传图片
最近要在微信上做个问卷调查,有个上传图片功能,折腾找了半天资料,都不好弄,最终打算调用微信提供的上传图片接口,实现上传图片功能!此功能最大的好处是可以在微信服务器上暂存图片,减少本地服务器图片的缓存, ...
- Matcher匹配器查找字符串指定内容
public static void main(String[] args) { String s = "我的手机号码是18988888888,曾经用过18987654321,还用过1881 ...