给c++入门新手用的一些模板-滚蛋吧c++(团队)论坛-团队讨论区-LZM's Blog

给c++入门新手用的一些模板

后续会继续更新的

迪杰斯特拉(未优化)

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=0x3f3f3f3f;
int mp[1005][1005];
int n,m,s;
int ans;
int dis[1005]={-1},vis[1005];
//迪杰斯特拉函数
void dij(int n,int s){
    //将所有的点距离设置为无穷
    for(int i=0;i<=n;i++){
        dis[i]=N;
    }dis[s]=0;//s为起点,s到s的点的距离为0
    //遍历所有的点
    for(int i=1;i<=n;i++){
        int u=0;//认为当前距离最短的点为0
        for(int j=1;j<=n;++j){
            if(!vis[j] and dis[j] < dis[u])u=j;//如果这个点没有选定且当为j点的距离比u的距离更短,对最短路径u点更新
        }vis[u]=1;//选定了u点,对u点进行标记
        for(int j=1;j<=n;j++){//遍历检查所有点
            if(mp[u][j]){//如果u到j点有边
                int w = mp[u][j];//获取u点到j点的距离
                if(dis[j]>dis[u]+w){//检查如果u点到j点的距离,小于原本j点的距离
                    dis[j]=dis[u]+w;//将到j点的距离数组更新。
                }
            }
        }
    }
}
signed main(){
    cin >> n >> m >> s;
    for(int i=1;i<=m;i++){
        int u,v,w;
        cin >> u >> v >> w;
        
        int tmp=mp[u][v]?mp[u][v]:N;//邻接矩阵储存图,如果该位置,没有边则设置为无限(既0x3f3f3f3f)。否则为原本的边与当前边的较小者。
        mp[u][v]=min(tmp,w); //人话就是处理重边
    }dij(n,s);//函数调用,n为点的个数,s为起点
    for(int i=1;i<=n;i++){//依次输出所有点从起点s的最短路径
        if(dis[i]==N)cout << -1 << " "; //不能到达则输出-1
        else cout << dis[i] << " ";//能到达输出最短路径
    } 
    return 0;
}

优化版本(优先队列)

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=0x3f3f3f3f3f3f3f;
int mp[1005][1005];
int n,m,s;
int dis[1005],vis[1005];
void dij(int n,int s){
    for(int i=1;i<=n;i++){
        dis[i]=N;
    }
    dis[s]=0;
    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> heap;
    heap.push({0,s});
    while(!heap.empty()){//主循环
        int u=heap.top().second;
        heap.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(int j=1;j<=n;j++){
            if(mp[u][j]){
                int w=mp[u][j];
                if(dis[j]>dis[u]+w){
                    dis[j]=dis[u]+w;
                    heap.push({dis[j],j});
                }
            }
        }
    }
}
signed main(){
    cin>>n>>m>>s;
    for(int i=1;i<=m;i++){
        int u,v,w;
        cin>>u>>v>>w;
        int tmp=mp[u][v]?mp[u][v]:N;//重边
        mp[u][v]=min(tmp,w);
    }dij(n,s);
    for(int i=1;i<=n;i++){
        if(dis[i]==N)cout<<-1<<" ";
        else cout<<dis[i]<<" ";
    }
    return 0;
}

贝尔曼福特

#include<bits/stdc++.h>
using namespace std;
#define int long long
struct node{
    int from,to,len;//出发点,要去的点,长度
}a[10010];
int n,m,s,t;//依托不知名的东西,分别是节点数,边数,起点,终点

int dis[10010] ;
signed main(){
    cin >> n >> m >> s >> t;
    for(int i=1;i<=n;i++){
       dis[i] = 1e9; //初始化数组
    }
    dis[s]=0;//起点
    for(int i=1;i<=m;i++){
        cin >> a[i].from >> a[i].to >> a[i].len;//输入图的相关数据
	}
    int from,to,len;//出发点,要去的点,长度
    for(int k=1;k<n;k++){
        bool p=false;
        for(int i=1;i<=m;i++){
            from=a[i].from,to=a[i].to,len=a[i].len;//赋值。
            if(dis[to]>dis[from]+len){
                p=true;
                dis[to]=dis[from]+len;
            }
            //判断走到to这个点能否更新最短距离
        }if(p==false)break;                                                                                                                         
    }
    cout << dis[t];
    //输出走到t的最短路径
    return 0;
}

SPFA

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,s,t;
int dis[10010],vis[10010],mp[5010][5010];
signed main(){
    cin >> n >> m >> s >>t;
    for(int i=1;i<=n;i++){
        dis[i]=1e9; //初始化数组
    }for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            mp[i][j]=1e9;//初始化*2
        }
    }for(int i = 1;i <= m;i++){
        int s,t,v;
        cin >> s >> t >> v;
        mp[s][t]=v;//输入图并储存
	}dis[s]=0;
    vis[s]=1;
    queue<int> a;
    a.push(s);
    while(a.size()){
        int u=a.front();//取出队首
        a.pop();//取出
        vis[u]=0;//将该点标记为不在队列中
        for(int i=1;i<=n;i++){
            if(dis[i]>dis[u]+mp[u][i]){
                dis[i]=dis[u]+mp[u][i];//更新,进行松弛操作
                if(!vis[i]){//如果该点被更改
                    vis[i]=1; //标记
                    a.push(i);//入队
                }
            }
        }
    }
    cout << dis[t];
    return 0;
}

弗洛伊德

#include<bits/stdc++.h>
using namespace std;
int n,m,ans=0;//计数器
int dis[101][101],a[10001];//距离数组及必经之路数组
int main(){
    cin >> n >> m;
    for(int i=1;i<=m;i++)cin >> a[i];//输入必经之路
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin >> dis[i][j];//输入距离
        }
    }for(int k=1;k<=n;k++){//中转点
        for(int i=1;i<=n;i++){//在邻接矩阵的x坐标
            for(int j=1;j<=n;j++){ //在邻接矩阵的y坐标
               dis[i][j]=min(dis[i][j],dis[k][j]+dis[i][k]);//松弛操作
            }
        }
    }for(int i=2;i<=m;i++){
        ans+=dis[a[i-1]][a[i]];//计数
    }cout << ans;
    return 0;
}

归并排序:

#include<iostream>
using namespace std;
int n,a[1010],temp[1010];
void MergeSort(int l,int r){
	//2.1、递归的结束条件:只有一个数,就不用再递归下去,直接返回 
	if(l==r){
        return ;
    }
	//2.2、找到中间位置,递归处理左半部分,递归处理右半部分 
	int mid=(l+r)/2;
	MergeSort(l,mid);
    MergeSort(mid+1,r);
	//3、合并,两个序列分别为[l,mid] 和 [mid+1,r],从最左边开始,依次比较,小的数放入结果数组temp,下标右移 
	int i=l,j=mid+1,k=l;
	while(i<=mid and j<=r){
		if(a[i]<=a[j])
			temp[k++] = a[i++];
		else
			temp[k++] = a[j++];
	}
	//3.1、判断两个序列是否有剩余,有剩余的,全部放入结果数组 temp 
	while(i<=mid)
		temp[k++]=a[i++];
	while(j<=r)
		temp[k++]=a[j++];
	//4、把结果数组 temp 重新赋给 a 数组 
    for(int i=l;i<=r;i++)
        a[i]=temp[i];
}
int main(){
	//1、定义变量 n 和数组 
	cin >> n;
	for(int i=1;i<=n;i++)
		cin >> a[i];
	//2、划分,左端点为 1,右端点为 n,递归处理 
	MergeSort(1,n);
	for(int i=1;i<=n;i++)
		cout << a[i]<<" "; 
	return 0;
}

快速排序

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
int a[N];
int n;
void partition(int a[],int l,int r){
    int x=a[l],i=l,j=r;
    if(l>=r) return;
    while(i<j) {
        while(i<j and a[j]>=x) j--;
        a[i]=a[j];
        while(i<j and a[i]<=x) i++;
        a[j]=a[i];
        
    }a[i]=x;
    partition(a,l,i-1);
    partition(a,i+1,r);
}

int main(){
   	cin>>n; 
    for(int i=0;i<n;i++)  cin>>a[i];
    partition(a,0,n-1);
    for(int i=0;i<n;i++)cout << a[i]<<" ";
    return 0;
}

埃氏筛

#include <bits/stdc++.h>
using namespace std;
int main(){
    int a;
    cin >> a;
    int sz[10000005]={0};
    sz[1]=1;
    for(int i=1;i*i<=a;i++){
        if(sz[i]==0){
            for(int j=2*i;j<=a;j+=i){
                sz[j]=1;
            }
        }
    }for(int i=1;i<=a;i++){
        if(sz[i]==0){
            cout << i << " ";
        }
    }
    return 0;
}

欧拉筛

#include <bits/stdc++.h>
using namespace std;
#define int long long
int sz[10000005];
int prime[10000005];
signed main(){
    int a;
    cin >> a;
    int cnt = 0;
    sz[1] = 1;
    for(int i=2;i<=a;i++){
        if(sz[i]==0){
            prime[cnt++] = i;
        }for(int j=0;j<cnt and i*prime[j]<=a;j++){
            sz[i*prime[j]] = 1;
            if(i%prime[j]==0){
                break;
            }
        }
    }for(int i=1;i<=a;i++){
        if(sz[i]==0){
            cout << i << " ";
        }
    }
    return 0;
}

最长上升子序列(lis)

#include <bits/stdc++.h>
using namespace std;
#define int long long
int sz[1005]={},lis[1005]={};
signed main(){
    int a;
    cin >> a;
    for(int i=1;i<=a;i++){
        cin >>sz[i];
    }for(int i=1;i<=a;i++){//lis
        lis[i]=1;
        for(int j=1;j<i;j++){ 
            if(sz[j]<sz[i]){
                lis[i]=max(lis[i],lis[j]+1);
            }
        }
    }
    cout << lis[a];
    return 0;
}

最长下降子序列(lds)

#include <bits/stdc++.h>
using namespace std;
#define int long long
int sz[1005]={},lds[1005]={};
signed main(){
    int a;
    cin >> a;
    for(int i=1;i<=a;i++){
        cin >>sz[i];
    }for(int i=1;i<=a;i++){//lds
        lds[i]=1;
        for(int j=1;j<i;j++){ 
            if(sz[j]>sz[i]){
                lds[i]=max(lds[i],lds[j]+1);
            }
        }
    }
    cout << lds[a];
    return 0;
}

堆的实现简易版(STL,作者刚开始自学):

#include <bits/stdc++.h>
using namespace std;
priority_queue<int, vector<int>, greater<int>> heap;//小根堆
vector<int> a;//输入
int main(){
    int x;
    heap.top();//取堆顶元素
    heap.pop();//删除堆顶元素
    heap.push(x);//将元素 x 插入堆
    heap.size();//堆的大小
    heap.empty();//判空
    return 0;
}

堆的数组实现(可能有点AI风,因为用了下AI修正)

#include <bits/stdc++.h>
using namespace std;
class MinHeap{
private:
    vector<int> heap;  // 用vector存储堆数据,索引0作堆顶
    void heapifyUp(int index){// 上浮调整
        while(index>0) {
            int parent=(index-1)/2; // 计算父节点索引
            if(heap[index]>=heap[parent]) break; // 如果当前节点>=父节点,满足堆性质,退出
            swap(heap[index],heap[parent]); // 否则交换父子节点
            index=parent; // 向上检查
        }
    }
    void heapifyDown(int index){// 下沉调整
        int size=heap.size();
        while(1) {
            int left=2*index+1;   // 左孩子索引
            int right=2*index+2;  // 右孩子索引
            int smallest=index;       // 假设当前节点最小
            if(left<size and heap[left]<heap[smallest]) // 找当前节点和左右孩子中最小的
                smallest=left;
            if(right<size and heap[right]<heap[smallest]) 
                smallest=right;
            if(smallest==index) break;  // 如果当前节点就是最小的,堆性质满足
            swap(heap[index], heap[smallest]);  // 否则交换
            index = smallest;  // 向下检查
        }
    }
public:
    void push(int value){// 插入元素:先放到末尾,然后上浮调整
        heap.push_back(value);
        heapifyUp(heap.size()-1);
    }// 删除堆顶:用最后一个元素替换堆顶,然后下沉调整
    void pop() {
        if(heap.empty()) return;        // 空堆直接返回
        heap[0]=heap.back();           // 末尾元素移到堆顶
        heap.pop_back();                 // 删除末尾元素
        if(!heap.empty()) heapifyDown(0); // 如果堆不为空,从堆顶开始下沉
    }// 获取堆顶元素(最小值)
    int top(){
        return heap.empty()?-1:heap[0];  // 空堆返回-1,否则返回堆顶
    }// 判断堆是否为空
    bool empty(){
        return heap.empty();
    }// 获取堆大小
    size_t size(){
        return heap.size();
    }
};
int main() {
    MinHeap heap;
    int n;
    cin >> n;
    return 0;
}
请登录后发表评论

LZM‘s AI

LZM‘s AI

LZM's Blog

LZM's Blog