P2573 [SCOI2012]滑雪(kruskal&bfs)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2573 [SCOI2012]滑雪(kruskal&bfs)相关的知识,希望对你有一定的参考价值。

P2573 [SCOI2012]滑雪(kruskal&bfs)

这个时间胶囊相当于每个边只用走一次,也就是答案对应的图的边权之和。

考虑从1开始 b f s bfs bfs能走的点和边,建立一个新图,然后在新图跑 k r u s k a l kruskal kruskal即可。

排序的时候 h v h_v hv为第一关键字, w w w为第二关键字。

因为要求点数尽量多,所以 h v h_v hv尽量大,在此基础上要求权最小即可。

时间复杂度: O ( n l o g n + m ) O(nlogn+m) O(nlogn+m)

// Problem: P2573 [SCOI2012]滑雪
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2573
// Memory Limit: 125 MB
// Time Limit: 5000 ms
// Date: 2021-12-17 11:06:56
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e5+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
const int hashmod[4] = 402653189,805306457,1610612741,998244353;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define ios ios::sync_with_stdio(false),cin.tie(nullptr) 
void Print(int *a,int n)
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 

template <typename T>		//x=max(x,y)  x=min(x,y)
void cmx(T &x,T y)
	if(x<y) x=y;

template <typename T>
void cmn(T &x,T y)
	if(x>y) x=y;

int n,m,H[N];
int h[N],cnt;
struct edge
	int to,nt,w;
e[M<<1];
struct E
	int u,v,w;
	bool operator<(const E&a)const
		return H[v]==H[a.v]?w<a.w:H[v]>H[a.v];
	
a[M<<1];
void add(int u,int v,int w)
	e[++cnt]=v,h[u],w,h[u]=cnt;

int sum,num;
bitset<N>vis;
void bfs()
	queue<int>q;q.push(1);sum++;vis[1] = 1;
	while(!q.empty())
		int u = q.front();q.pop();
		for(int i=h[u];i;i=e[i].nt)
			int v = e[i].to;
			a[++num] = u,v,e[i].w;
			if(!vis[v])
				q.push(v),vis[v] = 1;
				sum++;
			
		
	

int s[N];
int find(int x)
	return x==s[x]?x:s[x]=find(s[x]);

int main()
	scanf("%d%d",&n,&m);
	rep(i,1,n) scanf("%d",&H[i]),s[i] = i;
	rep(i,1,m)
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		if(H[u]>=H[v]) add(u,v,w);
		if(H[v]>=H[u]) add(v,u,w);
	
	bfs();
	int x = 0;
	ll ans = 0;
	sort(a+1,a+num+1);
	rep(i,1,num)
		int u = a[i].u,v=a[i].v,w=a[i].w;
		u=find(u),v=find(v);
		if(u!=v)
			s[u] = v;
			ans+=w;
			x++;
		
		if(x==sum - 1) break;
	
	printf("%d %lld\\n",sum,ans);
	return 0;

以上是关于P2573 [SCOI2012]滑雪(kruskal&bfs)的主要内容,如果未能解决你的问题,请参考以下文章

P2573 [SCOI2012]滑雪

题解Luogu P2573 [SCOI2012] 滑雪 最小生成树

[SCOI2012]滑雪与时间胶囊

[SCOI2012]滑雪与时间胶囊

2753: [SCOI2012]滑雪与时间胶囊

bzoj2753: [SCOI2012]滑雪与时间胶囊