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 ;
}