各种模版(普及组)

1.并查集

for(int i=1;i<=n;i++){
		fa[i]=i;
}//初始化 
int find(int x){
	if(fa[x]!=x){
		fa[x]=find(fa[x]);
	}
	return fa[x];
}//find father,这里用了路径压缩 
void merger(int x,int y){
	if(find(x)!=find(y)){
		fa[x]=y;
	}
}

2.各种高精(普及同模之后几乎没有了)

getline(cin,a);
	getline(cin,b);
	if(a.size()>b.size()){
		b=string((a.size()-b.size()),0)+b;
	}else{
		a=string(b.size()-a.size(),0)+a;
	}
	c='0'+a;
	for(int i=a.size()-1;i>=0;i--){
		c[i+1]=a[i]-'0'+b[i]-'0';
		//c[i+1]=a[i]-'0'-(b[i]-'0');
	}
	for(int i=a.size()-1;i>=0;i--){
		if(c[i]>=10){
			c[i+1]=c[i]/10;
			c[i]=c[i]%10;
		}
		//if(c[i]<0){
		//	c[i]=c[i]+10;
		//	c[i-1]=c[i]-1;
		//}
	}

3.归并排序(求逆序对)不断递归分解然后回的时候排序

void merger(int l,int mid,int r){
	int i=s;int j=mid+1;
	int k=s;
	while(i<=mid&&j<=r){
		if(a[i]>a[j]){
			zancun[k++]=a[j++];
			ans=mid-i+1;//从小到大排序,后面一定比他当前大 
		}else{
			zancun[k++]=a[i++];
		}
	}
	while(i<=mid){
		zancun[k++]=a[i++];
	}
	while(j<=r){
		zancun[k++]=a[j++];
	}
	for(int i=l;i<=r;i++){
		a[i]=zancun[i];
	}
}
void fen(int l,int r){
	if(l<=r){
		mid=(l+r)>>1;
		fen(l,mid);
		fen(mid+1,r);
		merger(l,mid,r);
	} 
}

4.二分答案最大值最小等问题一定可以用二分降复杂度

void check(int k){
	if(k满足条件){
		return true; 
	}else{
		return false;
	}
} 
int erfen(int l,int r){
	int ans;
	while(l<=r){
		int mid=(l+r)/2;
		if(check(mid)){
			ans=check(mid);
			l=mid+1;
		}else{
			r=mid;
		}
	}
	return ans;
}

5.链式前向星(他有一个优秀的性质在存双向边时,i^1就是令一条边)

struct node{
	int to;
	int next;
};
node edge[maxn*2];
int head[maxn];
int ecnt;
void add(int x,int y){
	edge[++ecnt].to=y;
	edge[ecnt].next=head[x];
	head[x]=ecnt;
}//这是最基础的,如果有需要还可以node里加信息, 

6.快速幂基于二进制求一个数的幂,后面数论很多要用到他;

int ans=0;
	while(b){
		if(b&1==1){
			ans=ans*a%m;
		}
		a=a*a%m;
		b=b/2;
	}

7.拓扑(将入度为0加入queue并且不断删点以更新入度)拓扑的括号化定里以后会在lca用到

queue<int>que;
	int into[maxn];//入度
	for(int i=1;i<=n;i++){
		if(into[i]==0){
			que.push(i);
		}
	}
	while(que.size()!=0){
		int x=que.top();
		for(int i=head[x];i;i=edge[i].next){
			int v=edge[i].to;
			into[v]--;
			if(into[v]==0){
				que.push(v);
			}
		}
	}

8.最短路--全源最短路floyd其基本思想是利用每个点去松弛每条边,更深理解见P1119 灾后重建

for(int k=1;k<=n;k++){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			f[i][j]=min(f[i][k]+f[k][j],f[i][j])
		}
	}
}

8.最短路--全源最短路johnson几乎用不到大体就是一遍spfa一遍dijkstra(几乎用不到)

#include<bits/stdc++.h>
using namespace std;
const long long maxn=1e9;
struct xing{
	int from;
	int to;
	int w;
};
struct node{
	int id;
	int dist;
	node(){
		
	}
	node(int nid,int ndist){
		id=nid;
		dist=ndist;
	}
	bool friend operator < (node a,node b){
		return a.dist>b.dist;
	}
};
priority_queue<node>pque;
int n,m,a,b,c;
xing xx[20009];
int head[20009],t[20009];
int flag[20009];
int ecnt;
long long h[20009],dist[20009];
bool spfa(int s){
	queue<int>q;
	memset(h,0x3f,sizeof(h));
	h[s]=0;
	flag[s]=1;
	q.push(s);
	while(q.size()!=0){
		int now=q.front();
		q.pop();
		flag[now]=0;
		for(int j=head[now];j;j=xx[j].from){
			int v=xx[j].to;
			if(h[v]>h[now]+xx[j].w){
				h[v]=h[now]+xx[j].w;
				if(flag[v]==0){
					flag[v]=1;
					q.push(v);
					t[v]++;
					if(t[v]==n+1){
						return false;
					}
				}
			}
		} 
	}
	return true;
}
void dijkstra(int s){
	for(int i=1;i<=n;i++){
		dist[i]=maxn;
	}
	memset(flag,0,sizeof(flag));
	pque.push(node(s,0));
	dist[s]=0;
	while(pque.size()!=0){
		int now=pque.top().id;
		pque.pop();
		if(flag[now]==1)continue;
		flag[now]=1;
		for(int j=head[now];j;j=xx[j].from){
			int v=xx[j].to;
			if(dist[v]>dist[now]+xx[j].w){
				dist[v]=dist[now]+xx[j].w;
				if(flag[v]==0){
					pque.push(node(v,dist[v]));	
				}
				
			}
		}
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>a>>b>>c;
		xx[++ecnt].to=b;
		xx[ecnt].from=head[a];
		xx[ecnt].w=c;
		head[a]=ecnt;
	}
	for(int i=1;i<=n;i++){
		a=0;
		b=i;
		c=0;
		xx[++ecnt].to=b;
		xx[ecnt].from=head[a];
		xx[ecnt].w=c;
		head[a]=ecnt;
	}
	if(spfa(0)==false){
		cout<<-1<<endl;
		return 0;
	}
	for(int i=1;i<=n;i++){
		for(int j=head[i];j;j=xx[j].from){
			xx[j].w+=h[i]-h[xx[j].to];
		}
	}
	for(int i=1;i<=n;i++){
		dijkstra(i);
		long long ans=0;
		for(int j=1;j<=n;j++){
			if(dist[j]==maxn){
				ans+=j*maxn;
			}else{
				ans+=j*(dist[j]+h[j]-h[i]);
			}
		}
		cout<<ans<<endl;
	}
}

9.dijlstra

struct xing{
	int to;
	int next;
	int w;
};
xing xx[2*maxn];
int head[maxn];
int cnt;
void add(int x,int y,int val){
	xing[++cnt].to=y;
	xing[cnt].next=head[x];
	xing[cnt].w=val;
	head[x]=cnt; 
}
struct node{
	int from;
	int to;
	int val;
	node(){
		
	}
	node(int nfrom,int nto,int nval){
		from=nfrom;
		to=nto;
		val=nval;
	}
	bool friend operator < (node a,node b){
		return a.val>b.val;
	}
};
priority<node>pque;
int dist[maxn];
int flag[maxn];
void dijkstra(){
	pque.push(ks);
	dist[ks]=0;
	while(pque.size()!=0){
		int now=pque.top();
		pque.pop();
		if(flag[now]==1){
			continue;
		}
		flag[now]=1;
		for(int i=head[now];i;i=edge[i].next){
			int v=edge[i].to;
			if(dits[v]>dist[now]+edge[i].val){
				dist[v]=dist[now]+edge[i].val;
				pque.push(v);
			}
		}
		
	}
}

10.spfa(判断负环)

queue<int>que;
int n;
bool spfa(){
	dist[s]=0;
	vis[s]=1;
	que.push(s);
	while(que.size()!=0){
		int now=que.front();
		que.pop();
		for(int i=head[now];i;i=edge[i].next){
			v=edge[i].to;
			val=edge[i].val;
			if(dist[v]>dis[now]+val){
                dist[v]=dis[now]+val
                cnt[v]=cnt[now]+1;
                if(cnt[v]>=n)return false;   
                if(!vis[v]){
                    que.push(v);
                    vis[v]=true;
                }
            }
		}
	}
	return true;
}

11.最小生成树.prim类似于dijkstra两种均是贪心

void prim(){
	flag[s]=1;
	pque.push(node(0,s,0));
	while(pque.size()!=0){
		int now=pque.top();
		pque.pop();
		if(flag[now]==1){
			continue;
		} 
		flag[now]=1;
		for(int i=head[now];i;i=edge[i].next){
			v=edge[i].to;
			if(flag[v]==0){
				pque.push(node(now,v,edge[i].val));
			}
		}
	}
}

12.kruskal并查集加sort

int find(int x){
	if(fa[x]!=x){
		fa[x]=find(fa[x]);
	}
	return fa[x];
}
void kruskal(){
	sort(edge+1,edge+1+m);
	for(int i=1;i<=n;i++){
		fa[i]=i;
	}
	for(int i=1;i<=m;i++){
		int a=edge[i].from;
		int b=edge[i].to;
		if(find(a)!=find(b)){
			fa[a]=b;
			ans.push("这一条边");
			ecnt++;
			if(ecnt==n-1){
				break;//一个树只有n-1边,so到了n-1直接break 
			} 
		}else{
			continue;
		} 
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值