【题目大意】

现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树。

【思路】

拖欠了三个月整(?)的题目,搞出来弄掉了……本年度写的时候姿势最丑的程序,完全不知道自己在搞些什么,晕乎乎的,算了。

首先,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 ;
}

最新文章

  1. UICollectionView + AFNetWorking 异步加载,局部刷新.
  2. css animation让图标不断旋转
  3. HDU4456-Crowd(坐标旋转+二位树状数组+离散化)
  4. Delphi 多文件拖放获取路径示例
  5. Python的基本语法,涵盖数据类型、循环判断、列表、map和set等
  6. HDOJ(HDU) 2192 MagicBuilding(用Java的Map做了下)
  7. BootStrap 模态框禁用空白处点击关闭,手动显示隐藏,垂直居中
  8. REST设计规则
  9. Git首次配置
  10. 《R语言入门与实践》第三章:R 对象
  11. 基于 Django2 实现邮箱注册登录功能
  12. servlet保存会话数据---利用隐藏域
  13. VUE项目实现页面跳转
  14. luoguP4705 玩游戏 分治FFT
  15. 51单片机和Arduino—闪烁灯实现
  16. EF基础知识小记一
  17. 2016/1/2 Python中的多线程(1):线程初探
  18. 【解决】SOUI向导生成项目(VC2013以上版本编译时)无法运行XP解决
  19. centos上tensorflow一键安装脚本
  20. bzoj 4412: [Usaco2016 Feb]Circular Barn

热门文章

  1. Kill windows和linux 进程
  2. python中的argparse模块
  3. 访问dubbo没有权限,通过ip进行跳转服务器,并通过有权限服务器代理访问
  4. 在 static table view 中增加date picker 并进行动态高度设定
  5. Java Redis 连接池 Jedis 工具类
  6. MySQL-5.5.49安装、多实例、主从复制
  7. 在 Visual Studio 中使用正则表达式
  8. Redis 集群使用(2)
  9. javascript方法--apply()
  10. java中的Map集合