蓝桥杯模板总结:

堆优化的DIJ单源最短路:

#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;
int read(){
	int x,f;
	x=0;f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
int n,m,s;
struct bnode{
	int cd;
	int v;
};
vector<bnode> dt[100009];
int bj[100009]={0};
int dis[100009]={0};
struct node{
	int xh;
	int dx;
};
struct cmp{
	
	bool operator() (node a,node b){
	return a.dx>b.dx;
	}
};
priority_queue<node,vector<node>,cmp> pp;

int main(){
	n=read();m=read();s=read();
	int ma,mb,mv;
	for(int i=1;i<=m;i++){
		ma=read();mb=read();mv=read();
		bnode tmp;
		tmp.cd=mb;tmp.v=mv;
		dt[ma].push_back(tmp);
	}
	for(int i=0;i<sizeof(dis)/4;i++){
		dis[i]=0x7fffffff;
	}
	dis[s]=0;
	pp.push((node){s,0});
	while(!pp.empty()){
		node tmp=pp.top();
		pp.pop();
		if(bj[tmp.xh]==1)continue;
		bj[tmp.xh]=1;
		for(int i=0;i<dt[tmp.xh].size();i++){
			if(bj[dt[tmp.xh][i].cd]==0&&dis[dt[tmp.xh][i].cd]>dis[tmp.xh]+dt[tmp.xh][i].v){
	//			cout<<dis[dt[tmp.xh][i].cd]<<" "<<dis[tmp.xh]+dt[tmp.xh][i].v<<endl;
				dis[dt[tmp.xh][i].cd]=dis[tmp.xh]+dt[tmp.xh][i].v;//更新距离 
				pp.push((node){dt[tmp.xh][i].cd,dis[dt[tmp.xh][i].cd]});//放进堆中; 
			}
		}
	}
	
	for(int i=1;i<=n;i++){
		cout<<dis[i]<<" ";
	}
	return 0;
} 

两个坑点:

①优先队列的结构体重定义排序,排序函数的规则和sort的规则相反,需要变一下。

②大数据量加快读

堆优化的SPFA单源最短路:

#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;
int read(){
	int x,f;
	x=0;f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
int n,m,s;
struct bnode{
	int cd;
	int v;
};
vector<bnode> dt[100009];
int bj[100009]={0};
int dis[100009]={0};
struct node{
	int xh;
	int dx;
};
struct cmp{
	
	bool operator() (node a,node b){
	return a.dx>b.dx;
	}
};
priority_queue<node,vector<node>,cmp> pp;

int main(){
	n=read();m=read();s=read();
	int ma,mb,mv;
	for(int i=1;i<=m;i++){
		ma=read();mb=read();mv=read();
		bnode tmp;
		tmp.cd=mb;tmp.v=mv;
		dt[ma].push_back(tmp);
	}
	for(int i=0;i<sizeof(dis)/4;i++){
		dis[i]=0x7fffffff;
	}
	dis[s]=0;
	bj[s]=1;
	pp.push((node){s,0});
	while(!pp.empty()){
		node tmp=pp.top();
		pp.pop();
//		if(bj[tmp.xh]==1)continue;
		bj[tmp.xh]=0;
		for(int i=0;i<dt[tmp.xh].size();i++){
			if(dis[dt[tmp.xh][i].cd]>dis[tmp.xh]+dt[tmp.xh][i].v){
	//			cout<<dis[dt[tmp.xh][i].cd]<<" "<<dis[tmp.xh]+dt[tmp.xh][i].v<<endl;
				dis[dt[tmp.xh][i].cd]=dis[tmp.xh]+dt[tmp.xh][i].v;//更新距离 
				if(bj[dt[tmp.xh][i].cd]!=1)
					pp.push((node){dt[tmp.xh][i].cd,dis[dt[tmp.xh][i].cd]});//放进堆中; 
			}
		}
	}
	for(int i=1;i<=n;i++){
		cout<<dis[i]<<" ";
	}
	return 0;
} 

注意:

①堆优化的spfa和dij很相似,代码重合度为98%,只是dij出队后不会再次入队,但是spfa出队后会再次入队。

②spfa可以用来求单源最长路,但是dij不可以。

单源最短路模板DIJ:

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
int n,m,s;
int read(){
	int x,f;
	x=0;f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
int bj[10009]={0};
int dis[10009]={0};
struct bian{
	int cd;
	int val;
};
vector<bian> dt[10009];
int getwz(){
	int minn=0x7fffffff;
	int minwz;
	for(int i=1;i<=n;i++){
		if(bj[i]==0&&dis[i]<minn){
			minn=dis[i];
			minwz=i;
		}
	}
	return minwz;
}
int main(){
	n=read();
	m=read();
	s=read();
	int ma,mb,mc;
	for(int i=1;i<=m;i++){
		ma=read();mb=read();mc=read();
		dt[ma].push_back((bian){mb,mc});
	}
	for(int i=0;i<=n;i++){
		dis[i]=0x7fffffff;
	}
	dis[s]=0;
	for(int i=1;i<n;i++){
		int wz=getwz();
		bj[wz]=1;
		for(int j=0;j<dt[wz].size();j++){
	//		cout<<dt[wz][j].cd<<" "<<bj[dt[wz][j].cd]<<" "<<dis[dt[wz][j].cd]<<" "<<dis[wz]<<" "<<dt[wz][j].val<<endl;
			if(bj[dt[wz][j].cd]==0&&dis[dt[wz][j].cd]>dis[wz]+dt[wz][j].val){
				dis[dt[wz][j].cd]=dis[wz]+dt[wz][j].val;
			}
		}
	}
	int sum=0;
	for(int i=1;i<=n;i++){
		cout<<dis[i]<<" ";
	}
	return 0;
}

FLOYD:多元最短路

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
int n,m;
int read(){
	int x,f;
	x=0;f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
int dp[1009][1009]={0};
int main(){
	n=read();
	m=read();
	int ma,mb,mc;
	for(int i=0;i<=n;i++){
		for(int j=0;j<=n;j++){
			dp[i][j]=100009;
		}
		dp[i][i]=0;
	}
	for(int i=1;i<=m;i++){
		ma=read();mb=read();mc=read();
		if(dp[ma][mb]>mc)
		dp[ma][mb]=mc;
	}
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(dp[i][j]>dp[i][k]+dp[k][j])
					dp[i][j]=dp[i][k]+dp[k][j];
			}
		}
	}
	return 0;
}

坑点:

①dp数组的初始值一定要赋值成比最长边还要大的数字,但是如果赋值成0x7fffffff,会导致任意两个不存在的边相加后溢出int范围变成负数,得到负边,所以初始值尽量保证两个初始值相加不超过int

②没边的赋值成最大值,有边的赋值成边权值即可。

最短路题型:如果要求所有点到任意一点的最短路,可以反向建图,再从单点跑一遍最短路即可。

堆排序:

#include<iostream>
#include<cstdio>
using namespace std;
int n;
int sz[1009]={0};
void jh(int wz){
	if(wz>n/2)return;
	int jl;
	if(sz[2*wz]>sz[2*wz+1])jl=2*wz;
	else jl=2*wz+1;
	if(sz[wz]<sz[jl]){
		swap(sz[jl],sz[wz]);
		jh(jl);	
	}
}
void gz(){
	
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>sz[i];
	}
	for(int i=n/2;i>=1;i--){
		jh(i);
	}
	for(int i=1;i<=n;i++){
		cout<<sz[1]<<" ";
		swap(sz[1],sz[n-i+1]);
		sz[n-i+1]=0;
		jh(1);
	}
	return 0;
}

堆排序:核心代码是jh函数,交换函数,将堆中以wz为根的堆重新构造堆;

线性筛素数:

#include<iostream>
#include<cstdio>
using namespace std;
int n,q;
int read(){
	int x,f;
	x=0;f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
int ss[100000009]={0};
int dj[100000009]={0};
int main(){
	n=read();
	q=read();
	ss[0]=1;
	ss[1]=1;
	int sum=0;
	for(int i=2;i<=n;i++){
		if(ss[i]==0)dj[++sum]=i;
		
		for(int j=1;j<=sum&&(long long)i*j<=n;j++){
			ss[dj[j]*i]=1;
			if(i%dj[j]==0)break;
		}
		
	}
	int qa;
	for(int i=1;i<=q;i++){
		qa=read();
		cout<<dj[qa]<<endl;
	}
	return 0;
}

gcd求最大公约数:

int gcd(int a,int b){
	if(b==0) return a;
	else return gcd(b,a%b);
} 

注意:两个数的乘积等于他们的最大公约数和最小公倍数的乘积。

快速幂:快速求a的b次方:

#include<iostream>
#include<cstdio>
using namespace std;
long long a,b,c;
long long ksm(long long a,long long b){
	if(b==1) return a%c;
	
	else {
		long long tmp=ksm(a,b/2)%c;
		return (((b%2==0? 1: a)%c*tmp)%c*tmp)%c;
	}
}
int main(){
	cin>>a>>b>>c;
	printf("%ld^%ld mod% ld=%ld",a,b,c,ksm(a,b)%c);
	return 0;
}

注意:求幂运算很容易炸int,所以一定longlong,并且要不断取余;

两数乘积的余数等于两个数取余的乘积。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值