【BZOJ4452】[Cerc2015]Export Estimate 并查集

本文详细解析了BZOJ4452题目,通过使用并查集算法来解决图论问题,重点在于如何通过调整边权阈值lim来生成新的图,并计算新图的点数和边数。文章提供了完整的代码实现,展示了如何在删除点的过程中更新图的结构。

【BZOJ4452】[Cerc2015]Export Estimate

Description

给你一个n个点m条边的无向图,每条边有权值,我们可以选择一个整数lim来生成一个新的图,过程如下: 
1.先将原图中边权小于lim的边删掉 
2.依次从1到n枚举每个点 
(a)如果这个点没有边于它相连,这个点将会被删去 
(b)如果这个点只与两条不相同的边x,y相连,设这两条边的另一个点分别为a,b,如果a,b和这个点都不相同(a,b可以相同),则依次做如下操作: 
(i)删去边x,y 
(ii)删去这个点 
(iii)在a,b之间建立一条新的边 
下面这个例子lim=95: 
 
数据保证原图没有重边和自环,但不保证经过如上操作后的图没有重边和自环。 
现在我们想知道当lim取若干值时,由原图生成的新图的点数和边数是多少。 

Input

第一行两个数n,m,表示原图有n点m条边。 
接下来m行,每行三个数a,b,c,表示a和b之间有一条边权为c的双向边。 
接下来一行一个数q,表示有q次询问。 
接下来一行q个数,k1,k2,...,kq。 

Output

总共q行,每行两个数,表示lim取ki时,生成的新图的点数和边数 

Sample Input

Sample Input1:
6 7
1 2 20
2 3 80
2 5 100
3 5 50
3 4 100
5 6 90
4 6 100
4
25 75 85 95
Sample Input2:
10 14
2 7 150
1 2 100
2 3 150
3 1 200
1 4 60
4 5 20
2 5 100
5 6 90
6 7 120
7 5 130
6 8 50
8 9 200
9 10 200
10 7 200
5
300 50 95 100 110

Sample Output

Sample Output1:
2 3
1 1
2 1
4 2
Sample Output2:
0 0
6 9
4 5
4 5
5 4
数据范围:
1<=n<=300000
1<=m<=300000
0<=c<=300000
1<=q<=300000
0<=ki<=300000

题解:发现在删除一个点的时候,其余点的度数不变,除了形成自环的情况,再结合几个例子就能发现:

最后的点数=n-度数为0的点的个数-度数为2的点的个数+环数
最后的边数=m-度数为2的点的个数+环数

所以用并查集来维护有几个环即可,具体地,维护一个连通块中点的个数以及度数为2的点的个数,如果相等则说明这是一个环。

 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=300010;
int n,m,Q;
int s0,s2,cir;
struct node
{
	int a,b,c;
}p[maxn];
struct query
{
	int org,k;
}q[maxn];
int f[maxn],siz[maxn],sz[maxn],d[maxn],a1[maxn],a2[maxn];
bool cmpc(const node &a,const node &b)
{
	return a.c>b.c;
}
bool cmpk(const query &a,const query &b)
{
	return a.k>b.k;
}
int find(int x)
{
	return (f[x]==x)?x:(f[x]=find(f[x]));
}
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
	while(gc>='0'&&gc<='9')	ret=ret*10+(gc^'0'),gc=getchar();
	return ret*f;
}
int main()
{
	n=rd(),m=rd();
	int i,j,a,b;
	for(i=1;i<=m;i++)	p[i].a=rd(),p[i].b=rd(),p[i].c=rd();
	sort(p+1,p+m+1,cmpc);
	Q=rd();
	for(i=1;i<=Q;i++)	q[i].org=i,q[i].k=rd();
	sort(q+1,q+Q+1,cmpk);
	for(i=1;i<=n;i++)	siz[i]=1,f[i]=i;
	s0=n;
	for(i=j=1;i<=m;i++)
	{
		for(;j<=Q&&q[j].k>p[i].c;j++)
			a1[q[j].org]=n-s0-s2+cir,a2[q[j].org]=i-1-s2+cir;
		s0-=(!d[p[i].a])+(!d[p[i].b]),s2-=(d[p[i].a]==2)+(d[p[i].b]==2);
		a=find(p[i].a),b=find(p[i].b);
		cir-=(siz[a]==sz[a])+(a!=b&&siz[b]==sz[b]);
		sz[a]-=(d[p[i].a]==2),sz[b]-=(d[p[i].b]==2);
		d[p[i].a]++,d[p[i].b]++;
		s2+=(d[p[i].a]==2)+(d[p[i].b]==2);
		sz[a]+=(d[p[i].a]==2),sz[b]+=(d[p[i].b]==2);
		if(find(a)!=find(b))	siz[b]+=siz[a],sz[b]+=sz[a],f[a]=b;
		cir+=(siz[b]==sz[b]);
	}
	for(;j<=Q;j++)	a1[q[j].org]=n-s0-s2+cir,a2[q[j].org]=m-s2+cir;
	for(i=1;i<=Q;i++)	printf("%d %d\n",a1[i],a2[i]);
	return 0;
}

 

 

转载于:https://www.cnblogs.com/CQzhangyu/p/7859648.html

内容概要:本文档详细介绍了基于直驱永磁同步发电机(PMSG)的1.5MW风力发电系统在Simulink环境下的建模与仿真全过程,涵盖了风力机空气动力学模型、PMSG电磁特性建模、不可控整流与逆变电路、直流环节、空间矢量脉宽调制(SVPWM)技术以及核心控制策略的设计。重点实现了最大功率点跟踪(MPPT)控制以提升风能捕获效率,并构建了电压外环与电流内环协同工作的双闭环控制系统,通过仿真验证了系统在不同风速条件下稳定运行的能力及动态响应性能。; 适合人群:适用于具备电力系统、电机控制理论基础及Simulink仿真操作经验的研究生、科研人员和从事新能源发电系统开发的工程技术人员;特别适合正在进行风电系统建模、控制算法研究或完成相关毕业设计的专业人士。; 使用场景及目标:①深入理解直驱式PMSG风力发电系统的整体架构与工作机理;②掌握从物理部件建模到控制策略实现的完整Simulink仿真流程;③学习并复现MPPT控制、双闭环控制等关键技术方案;④为后续开展低电压穿越、并网稳定性分析、故障诊断等高级课题提供可靠的仿真平台支撑。; 阅读建议:建议结合Matlab/Simulink软件动手实践,逐模块搭建模型,重点关注各控制环节的参数设计与调试方法,同时可参照文中提供的其他风电相关资源进行拓展学习与对比分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值