1.排序算法
快速排序
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int Arr[N];
void qsort(int l,int r){
int t = Arr[l];
int i = l;
int j = r;
while(i<j){
while(Arr[j]>=t&&i<j) j--;
while(Arr[i]<=t&&i<j) i++;
swap(Arr[i],Arr[j]);
}
swap(Arr[l],Arr[i]);
if(i<r) qsort(i+1,r);
if(j>l) qsort(l,j-1);
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>Arr[i];
qsort(0,n-1);
for(int i=0;i<n;i++) cout<<Arr[i]<<" ";
return 0;
}
归并排序
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int Arr[N],temp[N];
void merge_sort(int l,int r){
if(l>=r) return ;
int mid = l + r >> 1;
int i = l;
int j = mid + 1;
int k = 0;
merge_sort(l,mid);
merge_sort(mid+1,r);
while(i<=mid&&j<=r){
if(Arr[i]<=Arr[j]) temp[k++] = Arr[i++];
else temp[k++] = Arr[j++];
}
while(i<=mid) temp[k++] = Arr[i++];
while(j<=r) temp[k++] = Arr[j++];
for(i=0;i<k;i++) Arr[l+i] = temp[i];
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>Arr[i];
merge_sort(0,n-1);
for(int i=0;i<n;i++) cout<<Arr[i]<<" ";
return 0;
}
堆排序
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int heap[N];
int n,k;
void down_adjust(int pos){
int i = pos;
int j = i * 2;
while(j<=n){
if(j+1<=n&&heap[j]>heap[j+1]) j = j + 1;
if(heap[i]>heap[j]) {
swap(heap[i],heap[j]);
i = j;
j = i * 2;
}
else break;
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>heap[i];
for(int i=n/2;i>=1;i--) down_adjust(i);
while(n){
cout<<heap[1]<<" ";
heap[1] = heap[n--];
down_adjust(1);
}
return 0;
}
2.高精度
加法高精度
#include<bits/stdc++.h>
using namespace std;
void add(vector<int>&A,vector<int>&B){
vector<int> C;
int t = 0;
for(int i=0;i<A.size()||i<B.size();i++){
if(i<A.size()) t+=A[i];
if(i<B.size()) t+=B[i];
C.push_back(t%10);
t/=10;
}
if(t) C.push_back(1);
for(int i=C.size()-1;i>=0;i--) cout<<C[i];
}
int main(){
string a,b;
vector<int> A,B;
cin>>a>>b;
for(int i=a.length()-1;i>=0;i--) A.push_back(a[i]-'0');
for(int i=b.length()-1;i>=0;i--) B.push_back(b[i]-'0');
add(A,B);
return 0;
}
减法高精度
#include<bits/stdc++.h>
using namespace std;
bool cmp(string a,string b){
if(a.length()<b.length()) return false;
for(int i=0;i<a.length();i++){
if(a[i]<b[i]) return false;
}
return true;
}
void minu(vector<int>&A,vector<int>&B){
int t = 0;
vector<int> C;
for(int i=0;i<A.size();i++){
t = A[i] - t;
if(i<B.size()) t -= B[i];
C.push_back((t+10)%10);
if(t<0) t = 1;
else t = 0;
}
while(C.size()>1&&C.back()==0) C.pop_back();
for(int i=C.size()-1;i>=0;i--) cout<<C[i];
}
int main(){
string a,b;
vector<int> A,B;
cin>>a>>b;
if(cmp(a,b)==false) {
swap(a,b);
cout<<"-";
}
for(int i=a.length()-1;i>=0;i--) A.push_back(a[i]-'0');
for(int i=b.length()-1;i>=0;i--) B.push_back(b[i]-'0');
minu(A,B);
return 0;
}
乘法高精度
#include<bits/stdc++.h>
using namespace std;
void multi(vector<int>&A,int b){
vector<int> C;
int t = 0;
for(int i=0;i<A.size()||t;i++){
if(i<A.size()) t+=A[i]*b;
C.push_back(t%10);
t/=10;
}
while(C.size()>1&&C.back()==0) C.pop_back();
for(int i=C.size()-1;i>=0;i--) cout<<C[i];
}
int main(){
string a;
int b;
vector<int> A;
cin>>a>>b;
for(int i=a.length()-1;i>=0;i--) A.push_back(a[i]-'0');
multi(A,b);
return 0;
}
除法高精度
#include<bits/stdc++.h>
using namespace std;
void div(vector<int>&A,int b,int &r){
vector<int> C;
r = 0;
for(int i=A.size()-1;i>=0;i--){
r = r * 10 + A[i];
C.push_back(r/b);
r%=b;
}
reverse(C.begin(),C.end());
while(C.size()>1&&C.back()==0) C.pop_back();
for(int i=C.size()-1;i>=0;i--) cout<<C[i];
cout<<endl;
cout<<r;
}
int main(){
string a;
int b,r;
vector<int> A;
cin>>a>>b;
for(int i=a.length()-1;i>=0;i--) A.push_back(a[i]-'0');
div(A,b,r);
return 0;
}
3.二分查找
lower_bound && upper_bound
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int Arr[N],m,n,temp;
int lower_bound(int data){
int left = 0;
int right = n-1;
int mid;
while(left<right){
mid = (left+right) / 2;
if(Arr[mid]>=data) right = mid;
else left = mid + 1;
}
if(Arr[left]!=data) return -1;
else return left;
}
int upper_bound(int data){
int left = 0;
int right = n-1;
int mid;
while(left<right){
mid = (left+right+1)/2;
if(Arr[mid]<=data) left = mid;
else right = mid - 1;
}
if(left+1>n-1) return -1;
else return left + 1;
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++) cin>>Arr[i];
while(m--){
cin>>temp;
if(lower_bound(temp)==-1) cout<<"-1 -1"<<endl;
else cout<<lower_bound(temp)<<" "<<upper_bound(temp)<<endl;
}
return 0;
}
4.树
已知前序和中序还原树
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n,in[N],pre[N];
struct node{
int data;
node *lchild;
node *rchild;
};
node *build_tree(int prel,int prer,int inl,int inr){
if(prel>prer) return NULL;
node *root = new node;
root->data = pre[prel];
int k,num;
for(k=inl;k<=inr;k++) if(in[k]==pre[prel]) break;
num = k - inl;
root->lchild = build_tree(prel+1,prel+num,inl,k-1);
root->rchild = build_tree(prel+num+1,prer,k+1,inr);
return root;
}
int main(){
cin>>n;
for(int i=0;i<n;i++) cin>>pre[i];
for(int i=0;i<n;i++) cin>>in[i];
node *root = build_tree(0,n-1,0,n-1);
return 0;
}
已知后序和中序还原树
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n,in[N],post[N];
struct node{
int data;
node *lchild;
node *rchild;
};
node *build_tree(int inl,int inr,int posl,int posr){
if(posl>posr) return NULL;
node *root = new node;
root->data = post[posr];
int k,num;
for(k=inl;k<=inr;k++){
if(in[k]==post[posr]) break;
}
num = k - inl;
root->lchild = build_tree(inl,k-1,posl,posl+num-1);
root->rchild = build_tree(k+1,inr,posl+num,posr-1);
}
void pre(node *root){
if(root==NULL) return ;
cout<<root->data<<" ";
pre(root->lchild);
pre(root->rchild);
}
int main(){
cin>>n;
for(int i=0;i<n;i++) cin>>in[i];
for(int i=0;i<n;i++) cin>>post[i];
node *root = build_tree(0,n-1,0,n-1);
pre(root);
return 0;
}
二叉搜索树(BST)
#include<bits/stdc++.h>
using namespace std;
struct node{
int data;
node *lchild;
node *rchild;
};
void build_BST(node *&root,int v){
if(root==NULL){
root = new node;
root->data = v;
root->lchild = root->rchild = NULL;
return ;
}
else if(root->data<v) build_BST(root->rchild,v);
else build_BST(root->lchild,v);
}
int main(){
node *root = NULL;
int n,temp;
cin>>n;
for(int i=0;i<n;i++){
cin>>temp;
build_BST(root,temp);
}
return 0;
}
并查集(路径压缩)
#include<bits/stdc++.h>
using namespace std;
int father[10001];
void init(int n){
for(int i=0;i<n;i++) father[i] = i;
}
int find_father(int x){
if(x==father[x]) return x;
return father[x] = find_father(father[x]);
}
void Union(int u,int v){
int fu = find_father(u);
int fv = find_father(v);
if(fu!=fv) father[fu] = fv;
}
int main(){
int n,m,u,v,w;
cin>>n>>m;
init(n);
for(int i=0;i<n;i++){
cin>>u>>v;
Union(u,v);
}
while(m--){
cin>>u>>v;
if(find_father(u)==find_father(v)) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
二叉堆(down_adjust)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int heap[N],n;
void down_adjust(int low,int high){
int i = low;
int j = i * 2;
while(j<=high){
if(j+1<=high&&heap[j+1]<heap[j]) j = j + 1;
if(heap[i]>heap[j]){
swap(heap[i],heap[j]);
i = j;
j = i * 2;
}
else break;
}
}
void create_heap(){
for(int i=n/2;i>=1;i--) down_adjust(i,n);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>heap[i];
create_heap();
for(int i=1;i<=n;i++) cout<<heap[i]<<" ";
return 0;
}
二叉堆(up_adjust)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int heap[N],t,n,idx;
void up_adjust(int high){
int i = high;
int j = i / 2;
while(j>=1){
if(heap[j]>heap[i]){
swap(heap[i],heap[j]);
i = j;
j = i / 2;
}
else break;
}
}
void insert(int x){
heap[++idx] = x;
up_adjust(idx);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>t;
insert(t);
}
for(int i=1;i<=n;i++) cout<<heap[i]<<" ";
return 0;
}
5.图
Dijkstra求单源最短路(堆优化+链式前向星)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000001;
int vis[maxn],dis[maxn],first[maxn],pre[maxn];
int cnt;
struct node{
int to;
int weight;
bool operator < (const node &temp) const{
return weight > temp.weight;
}
};
struct Graph{
int to;
int weight;
int next;
}G[maxn];
void add(int u,int v,int w){
G[++cnt].to = v;
G[cnt].weight = w;
G[cnt].next = first[u];
first[u] = cnt;
}
priority_queue<node> q;
void Dijkstra(int s){
fill(dis,dis+maxn,INT_MAX);
dis[s] = 0;
pre[s] = s;
q.push((node){s,0});
while(!q.empty()){
node temp = q.top();
q.pop();
if(vis[temp.to]) continue;
vis[temp.to] = 1;
for(int i=first[temp.to];i!=-1;i=G[i].next){
int end = G[i].to;
if(dis[end] > dis[temp.to] + G[i].weight){
dis[end] = dis[temp.to] + G[i].weight;
pre[end] = temp.to;
if(!vis[end]) q.push((node){end,dis[end]});
}
}
}
}
void find_path(int start,int end){
if(start==end){
cout<<start;
return ;
}
else find_path(start,pre[end]);
cout<<"-->"<<end;
}
int main(){
fill(first,first+maxn,-1);
int m,n,u,v,w,start,end;
cin>>n>>m;
for(int i=0;i<m/2;i++){
cin>>u>>v>>w;
add(u,v,w);
add(v,u,w);
}
cin>>start>>end;
Dijkstra(start);
find_path(start,end);
cout<<endl;
cout<<dis[end];
return 0;
}
SPFA求单源最短路(图中含负环)(链式前向星+堆优化)
#include<bits/stdc++.h>
using namespace std;
const int N = 10010;
int dis[N],vis[N],first[N],de[N],cnt,m,n,u,v,w;
struct Graphy{
int v;
int w;
int next;
}G[N];
void add(int u,int v,int w){
G[++cnt].v = v;
G[cnt].w = w;
G[cnt].next = first[u];
first[u] = cnt;
}
struct node{
int v;
int w;
bool operator < (const node&temp) const{
return temp.w < w;
}
};
bool SPFA(int s){
de[s]++;
dis[s] = 0;
vis[s] = 1;
priority_queue<node> q;
q.push(node{s,0});
while(!q.empty()){
node top = q.top();
q.pop();
vis[top.v] = 0;
for(int i=first[top.v];i;i=G[i].next){
int e = G[i].v;
if(dis[e]>dis[top.v]+G[i].w){
dis[e] = dis[top.v] + G[i].w;
if(!vis[e]) {
q.push(node{e,dis[e]});
de[e]++;
vis[e] = 1;
if(de[e]>=n) return true;
}
}
}
}
return false;
}
int main(){
fill(dis,dis+N,INT_MAX);
cin>>n>>m;
for(int i=0;i<m;i++){
cin>>u>>v>>w;
add(u,v,w);
}
for(int i=1;i<=n;i++){
if(dis[i]!=INT_MAX) continue;
if(SPFA(i)==true) {
cout<<"Yes";
return 0;
}
}
cout<<"No";
return 0;
}
Floyd求多源最短路径
#include<bits/stdc++.h>
using namespace std;
const int maxn = 101;
int dis[maxn][maxn],path[maxn][maxn];
void Floyd(int n){
for(int k=0;k<n;k++){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(dis[i][k]!=INT_MAX&&dis[k][j]!=INT_MAX&&dis[i][j]>dis[i][k]+dis[k][j]) {
dis[i][j] = dis[i][k]+dis[k][j];
path[i][j] = path[i][k];
}
}
}
}
}
void find_path(int x,int y){
int v = path[x][y];
cout<<x;
while(v!=y){
cout<<"->"<<v;
v = path[v][y];
}
cout<<"->"<<y;
}
int main(){
int n,m,u,v,w,start,end;
cin>>n>>m>>start>>end;
fill(dis[0],dis[0]+maxn*maxn,INT_MAX);
for(int i=0;i<n;i++) dis[i][i] = 0;
for(int i=0;i<m;i++){
cin>>u>>v>>w;
dis[u][v] = w;
path[u][v] = v;
}
Floyd(n);
if(start==end) cout<<start<<"->"<<end<<":0";
else find_path(start,end);
return 0;
}
求最小生成树—Kruskal算法
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000001;
int father[maxn];
struct Edge{
int u;
int v;
int dis;
}ed[maxn];
bool cmp(Edge a,Edge b){
return a.dis < b.dis;
}
void init(int n){
for(int i=1;i<=n;i++) father[i] = i;
}
int find_father(int x){
if(x==father[x]) return x;
int temp = find_father(father[x]);
return temp;
}
int Kruskal(int n,int m){
int ans = 0;
int num_Edge = 0;
for(int i=0;i<m;i++){
int fu = find_father(ed[i].u);
int fv = find_father(ed[i].v);
if(fu!=fv){
father[fu] = fv;
ans+=ed[i].dis;
num_Edge++;
if(num_Edge==n-1) break;
}
}
if(num_Edge!=n-1) return -1;
else return ans;
}
int main(){
int n,m;
cin>>n>>m;
init(n);
for(int i=0;i<m;i++) cin>>ed[i].u>>ed[i].v>>ed[i].dis;
sort(ed,ed+m,cmp);
cout<<Kruskal(n,m);
return 0;
}
求最小生成树—Prime算法
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000001;
int dis[maxn],vis[maxn],first[maxn],cnt;
struct Graph{
int to;
int weight;
int next;
}G[maxn];
void add(int u,int v,int w){
G[++cnt].to = v;
G[cnt].weight = w;
G[cnt].next = first[u];
first[u] = cnt;
}
int prime(int n){
fill(dis,dis+maxn,INT_MAX);
dis[1] = 0;
int minn,u,ans=0;
for(int i=1;i<=n;i++){
minn = INT_MAX;
u = -1;
for(int j=1;j<=n;j++){
if(vis[j]==0&&dis[j]<minn){
minn = dis[j];
u = j;
}
}
if(u==-1) return -1;
vis[u] = 1;
ans+=dis[u];
for(int k=first[u];k;k=G[k].next){
int end = G[k].to;
if(vis[end]==0&&dis[end]>G[k].weight) dis[end] = G[k].weight;
}
}
return ans;
}
int main(){
int n,m,u,v,w;
cin>>n>>m;
for(int i=0;i<m;i++){
cin>>u>>v>>w;
add(u,v,w);
add(v,u,w);
}
int ans = prime(n);
if(ans==-1) cout<<"orz";
else cout<<ans;
return 0;
}
拓扑排序
#include<bits/stdc++.h>
using namespace std;
const int maxn = 10001;
vector<int> vi[maxn];
priority_queue<int,vector<int>,greater<int> > q;
int dis[maxn];
int main(){
int n,m,u,v,num=0;
cin>>n>>m;
for(int i=0;i<m;i++){
cin>>u>>v;
vi[u].push_back(v);
dis[v]++;
}
for(int i=1;i<=n;i++){
if(dis[i]==0) q.push(i);
}
while(!q.empty()){
int top = q.top();
cout<<top<<" ";
q.pop();
for(int i=0;i<vi[top].size();i++){
int end = vi[top][i];
dis[end]--;
if(dis[end]==0) q.push(end);
}
vi[top].clear();
num++;
}
return 0;
}