首页 > 其他分享 >2024.8.17

2024.8.17

时间:2024-08-17 21:48:23浏览次数:11  
标签:le 17 2024.8 最小 生成 int 权值 st


DATE #:20240817

ITEM #:DOC

WEEK #:SATURDAY

DAIL #:捌月拾肆

TAGS
	<iframe border="0" frameborder="no" height="86" marginheight="0" marginwidth="0" src="//music.163.com/outchain/player?type=2&id=2610346970&auto=0&height=66" width="330"></iframe>
< BGM = "快哉风 -- 黄金玉米王" >
< theme = oi-language >
< theme = oi-graph theory >
< [空] > 
< [空] >
取次花丛懒回顾,半缘修道半缘君 -- 元稹《离思五首·其四》

[P4208 [JSOI2008] 最小生成树计数]([P4208 JSOI2008] 最小生成树计数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn))

[JSOI2008] 最小生成树计数

题目描述

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

输入格式

第一行包含两个数,\(n\) 和 \(m\),其中 \(1 \le n \le 100\),\(1 \le m \le 1000\),表示该无向图的节点数和边数。每个节点用 \(1 \sim n\) 的整数编号。

接下来的 \(m\) 行,每行包含两个整数:\(a,b,c\),表示节点 \(a,b\) 之间的边的权值为 \(c\),其中 \(1 \le c \le 10^9\)。

数据保证不会出现自回边和重边。注意:具有相同权值的边不会超过 \(10\) 条。

输出格式

输出不同的最小生成树有多少个。你只需要输出数量对 \(31011\) 的模就可以了。

样例 #1

样例输入 #1

4 6
1 2 1
1 3 1
1 4 1
2 3 2
2 4 1
3 4 1

样例输出 #1

8

提示

数据范围及约定

对于全部数据,\(1 \le n \le 100\),\(1 \le m \le 1000\),\(1\leq c_i\leq 10^9\)。

先引入一个引理:

对于一个图的最小生成树,每个边权的边出现的次数是一样的

证明:模拟kruskal的过程,我们在给边排序时,交换同权的边并没有什么影响

那么我们先求解出最小生成树,并依次计算权值

考虑,当我们要加入权值为\(i\)的若干条边时,

前面加入的边已经使其变成了几个联通块,只要考虑用权值为\(i\)的边跑一次生成树数量即可,

之后对每个边权都依次操作

//2024.8.17
//by white_ice
//[JSOI2008] 最小生成树计数 |P4208
#include<bits/stdc++.h>
//#include"need.cpp"
using namespace std;
#define itn int
constexpr itn oo = 1003;
constexpr int mod = 31011;
struct nod{int x,y,z;}st[oo],sp[oo];
int cmp(nod a,nod b){return a.z<b.z;}
int n,m,t;
itn fa[oo],d[oo],c[oo],cnt,out,xx,yy;
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
__inline void dfs(int now,int k,int x){ 
	if (now>sp[x].y){
	  	if (k==d[x]) cnt++;
		return void();
	}
	int p[101];
	for (int i=1;i<=n;i++) p[i]=fa[i];
	xx=find(st[now].x);yy=find(st[now].y);
	if (xx!=yy){
	  	fa[xx]=yy;
	  	dfs(now+1,k+1,x);
	}
	for (int i=1;i<=n;i++) fa[i]=p[i];
	dfs(now+1,k,x);
}
main(void){
	//fre();
	cin.tie(0)->sync_with_stdio(0);
	cin >> n >> m;
	for (int i=1;i<=m;i++)cin >> st[i].x >> st[i].y >> st[i].z;
	sort(st+1,st+1+m,cmp);
	for (int i=1;i<=n;i++)fa[i]=i;
	st[0].z=-INT_MAX;t=0;
	for (int i=1;i<=m;i++){
	  	if (st[i].z==st[i-1].z){sp[t].y++;c[i]=t;}
		else {t++;sp[t].x=i;sp[t].y=i;c[i]=t;}
	}
	cnt=0;
	for (int i=1;i<=m;i++){
	  	xx=find(st[i].x);yy=find(st[i].y);
	  	if (xx!=yy){
	  	  	fa[xx]=yy;
	  	  	d[c[i]]++;
			cnt++;
		}
		if (cnt==n-1) break;
	}
	if (cnt!=n-1) {printf("0");exit(0);}
  	for (int i=1;i<=n;i++) fa[i]=i;
  	out=1;
  	for (int i=1;i<=t;i++)
    	if (d[i]>0){
    		cnt=0;
    		dfs(sp[i].x,0,i);
    		out=(out*cnt)%mod;
    		for (int j=sp[i].x;j<=sp[i].y;j++){
    	  		xx=find(st[j].x);yy=find(st[j].y);
    	  		if (xx!=yy)fa[xx]=yy;
		  	} 
    }
	cout << out << flush;
	exit (0);
} 

标签:le,17,2024.8,最小,生成,int,权值,st
From: https://www.cnblogs.com/white-ice/p/18365054

相关文章

  • 2024.8.17 鲜花
    コネクト交(か)わした约束(やくそく)忘(わす)れないよ『无法忘却彼此结下的约定』kawashitayakusokuwasurenaiyo目(め)を闭(と)じ确(たし)かめる『轻闭双眼再次确认』mewotojitashikameru押(お)し寄(よ)せた闇(やみ)振(ふ)り払(はら)って进(すす)むよ『驱......
  • [考试记录] 2024.8.17 csp-s模拟赛21
    T1Set解析思考+组合题场上只能想到暴力01背包再加上bitset优化,很好打。本应该有60pts(?或者更多),不曾想由于spj的一些未知原因喜提systemerror,全部cancelled。喜提0pts。......
  • dp题单vjudge 8.17
    HDU-1024MaxSumPlusPlushttps://acm.hdu.edu.cn/showproblem.php?pid=1024可以想到用dp过,但是无论时间和空间都不够,然后就不会了https://www.cnblogs.com/wuwangchuxin0924/p/6546901.html先写出转移方程,然后发现如果把其中一部分用其他的东西储存起来,就不需要重复寻找,直......
  • 8.17周总结
    本周学习的东西比较少,因为也要准备开学考试,本周将老师所留的PTA程序设计实验进行了结尾,并对CSS代码中的三个重要方面进行了学习,常规流,浮动。对于常规流,就是属于我们平常所写的一些代码,在这里我们了解了盒子的包含块,等于其父元素的内容盒;我学习了块盒,对于在块盒中,我知道了每个块盒......
  • 2024-08-17:用go语言,给定一个从0开始的整数数组nums和一个整数k, 每次操作可以删除数组
    2024-08-17:用go语言,给定一个从0开始的整数数组nums和一个整数k,每次操作可以删除数组中的最小元素。你的目标是通过这些操作,使得数组中的所有元素都大于或等于k。请计算出实现这个目标所需的最少操作次数。输入:nums=[2,11,10,1,3],k=10。输出:3。解释:第一次操作后,nums变......
  • 8.17
    ok 先来说一下近期变化  变胖了一点点 吃的太好了 and买了平板电脑今天刚到  然后今天闯了个红灯感觉非常不好spark环境搭建失败失败......................fuck尽管Spark相对于Hadoop而言具有较大优势,但Spark并不能完全替代Hadoop,Spark主要用于替......
  • 8.17日周记
    一、C语言学习1.pow函数用法:pow(底数,指数)例子:pow(x,2)=x²2.abs函数用法:abs(n)取n的绝对值3.strstr函数:搜索字符串1是否在字符串2中出现,若未搜索到,则返回NULL;若搜索到,则该函数返回第一次出现s2的地址。4.strcpy函数:用法:strcpy(字符串1,字符串2);strcpy函数将字符......
  • C240817C. 团队协作:二分答案+贪心
    C240817C.团队协作二分显然,但是被check难住了。以为只能把运动员按速度分成两类,然后二分图找最大匹配,但显然做不动。然后考场上就被卡住了………看了题解突然勾起了对一道题远古的记忆:总之也是二分之后是要看能不能全匹配上。然后当时用的就是sort之后贪心,发现这个贪心很对,......
  • C240817D. 模拟赛:树上dp(以i为起点)+set操作
    C240817D.模拟赛比较显然的树上dp,但是维护set比较烦考场上其实自己是定义\(f[i]\)是以\(i\)结尾,然后这样的话单次更新根本做不到\(O(logN)\).反应实在是太迟钝了,考场想“如果有一种只更新一条链的dp就好了”结果完全没想到只需变成以\(i\)开头就行了.积累经验吧。......
  • 基于SSM线上诊疗系统的设计与实现-附源码161711
    摘 要信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对线上诊疗等问题,对其研究分析,然后开发设计出基于Java的线上诊疗系统以解决问题。线上诊疗系......