Educational Codeforces Round 122 (Rated for Div. 2) E. Spanning Tree Queries(最小生成树 分段一次函数 暴力+离线)

该篇文章介绍了如何使用离线算法解决一个图论问题,即给定一个n个点m条边的无自环和重边图,对q次询问进行处理,每次询问指定边权为整数x与边权重之绝对差时,求最小生成树的总权值。关键在于构造一次函数并利用双指针技巧优化查询过程。

题目

n(n<=50)个点m(m<=300)条边保证联通的图,没有自环和重边

q(q<=1e7)次询问,每次给定一个整数x(x<=1e8),

询问当m条边的边权是abs(wi-x)时,图的最小生成树的值是多少

允许离线,最后只需将总共q个询问的答案异或在一起,输出最终的异或值

思路来源

jiangly代码

题解

当时赛中a了,但是写的很麻烦,现在补一下这个一次函数的写法

m条边枚举两两中点,C(m,2)+m个临界值变化的位置,去不去重无所谓

这m^2临界位置构成了若干个一次函数直线,询问两个临界为之间的时候,视为落在左边的直线上

那么就离线一下询问,双指针过一下这m^2个临界位置和q个询问,

对于每个询问x,找到不超过x的最大临界位置,

对其暴力做最小生成树求权值即可,

做好之后是一个形如y=coef*x+sum的形式,也就是一次函数y=kx+b

这个两年前没太想明白,现在看了看感觉差不多

考虑大于的值的贡献是w-x[now],小于的贡献是x[now]-w,

其中x[now]是临界位置,q[i]是询问的值,q[i]严格大于x[now],且严格小于x[now+1]

那么x固定时,每一条边都是对应有(k∈(-1,1),b)的一个贡献,线性相加即可

那么由于q[i]>x[now],所以当x[now]处,生成树有多个时,

需要选择coef最小的那个,才能使得一次函数在q[i]处的值最小

有个没弄懂的地方,是中点只能是(e[i].w+e[j].w+1)/2,也就是向上取整

改成(e[i].w+e[j].w)/2就wa了

大概感性理解了一下,感觉是左闭右开的直线形式,

代码

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<ll,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define scll(a) scanf("%lld",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
const int N=55,M=305,S=M*M,K=1e7+10;
int t,n,m,par[N],x[S],cnt,q[K];
int p,k,a,b,c;
ll ans;
struct edge{
	int u,v,w;
	void rd(){
		sci(u),sci(v),sci(w);
	}
}e[M];
int find(int x){
	return par[x]==x?x:par[x]=find(par[x]);
}
int main(){
	sci(n),sci(m);
	rep(i,1,m)e[i].rd();
	x[cnt++]=0;
	rep(i,1,m){
		rep(j,i,m){
			x[cnt++]=(e[i].w+e[j].w+1)/2;
		}
	}
	sort(x,x+cnt);
	scanf("%d%d%d%d%d",&p,&k,&a,&b,&c);
	rep(i,0,p-1){
		sci(q[i]);
	}
	rep(i,p,k-1){
		q[i]=(1ll*q[i-1]*a+b)%c;
	}
	sort(q,q+k);
	int now=-1;
	ll coef=0,sum=0;
	rep(i,0,k-1){
		int las=now;
		while(now+1<cnt && x[now+1]<=q[i]){
			now++;
		}
		//printf("i:%d q:%d las:%d now:%d\n",i,q[i],las,now);
		if(las<now){
			coef=sum=0;
			rep(j,1,n)par[j]=j;
			sort(e+1,e+m+1,[&](edge &u,edge &v){
				int w1=abs(u.w-x[now]),w2=abs(v.w-x[now]);
				if(w1^w2)return w1<w2;
				else return u.w>v.w; // w1=w2时 在x[now]处贡献相同 但是选大的w coef更小 一次函数y=kx+b x增至q[i]时 k减小 y减小
			});
			rep(j,1,m){
				int u=find(e[j].u),v=find(e[j].v);
				if(u==v)continue;
				par[v]=u;
				int w=e[j].w;
				//w>x[now] +w-x[now]
				//w<=x[now] +x[now]-w
				//printf("i:%d j:%d u:%d v:%d w:%d\n",i,j,u,v,w);
				if(w>x[now]){//q[i]介于x[now]与x[now+1]间 有多少个比x[now]大的,就是有多少个比q[i]大的,所以这么求coef
					coef--;
					sum+=w;
				}
				else{
					coef++;
					sum-=w;
				}
			}
		}
		//printf("i:%d q:%d coef:%lld sum:%lld add:%lld\n",i,q[i],coef,sum,coef*q[i]+sum);
		ans^=coef*q[i]+sum;
	}
	ptlle(ans);
	return 0;
}

【博士论文复现】【阻抗建模、验证扫频法】光伏并网逆变器扫频与稳定性分析(包含锁相环电流环)(Simulink仿真实现)内容概要:本文档是一份关于“光伏并网逆变器扫频与稳定性分析”的Simulink仿真实现资源,重点复现博士论文中的阻抗建模与扫频法验证过程,涵盖锁相环和电流环等关键控制环节。通过构建详细的逆变器模型,采用小信号扰动方法进行频域扫描,获取系统输出阻抗特性,并结合奈奎斯特稳定判据分析并网系统的稳定性,帮助深入理解光伏发电系统在弱电网条件下的动态行为与失稳机理。; 适合人群:具备电力电子、自动控制理论基础,熟悉Simulink仿真环境,从事新能源发电、微电网或电力系统稳定性研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握光伏并网逆变器的阻抗建模方法;②学习基于扫频法的系统稳定性分析流程;③复现高水平学术论文中的关键技术环节,支撑科研项目或学位论文工作;④为实际工程中并网逆变器的稳定性问题提供仿真分析手段。; 阅读建议:建议读者结合相关理论教材与原始论文,逐步运行并调试提供的Simulink模型,重点关注锁相环与电流控制器参数对系统阻抗特性的影响,通过改变电网强度等条件观察系统稳定性变化,深化对阻抗分析法的理解与应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小衣同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值