C++算法模板总结
排序
冒泡排序
//a为待排序数组,len为数组长度,数组下标从1开始
for(int i = 1;i<=len;i++){
for(int j = 1 ;j<=len-i;j++){
if(a[j]>a[j+1]){
int t ;
t = a[j];
a[j]= a[j+1];
a[j+1]=t;
//以上四行代码可用swap(a[j],a[j+1])代替
}
}
}
选择排序
for(int i=1;i<=n;i++){
int k=i;//k为最小的数的编号
for(int j=i+1;j<=n;j++){
if(a[j]<a[k]){
k=j;
}
}
if(k!=i){
int t;
t = a[i];
a[i]=a[k];
a[k] = t;
//以上四行可以用swap(a[i],a[k])代替
}
}
插入排序
for(int i=1;i<n;i++){
if(a[i]<a[i-1]){
int j=i-1;
int x=a[i];
while(j>-1&&x<a[j]){
a[j+1]=a[j];
j--;
}
a[j+1]=x;
}
}
快速排序
建议直接用sort
如果你想手敲,那就随便吧
#include <iostream>
using namespace std;
int a[10000],n,k;
void pai(int start,int end,bool flag){
int i=start,j=end;
if (start>=end){
return ;
}
while (i!=j){
if (flag){
while (a[j]>=a[start]&&j>i){
j--;
}
}
else{
while (a[j]<=a[start]&&j>i){
j--;
}
}
if (flag){
while (a[i]<=a[start]&&i<j){
i++;
}
}
else{
while (a[i]>=a[start]&&i<j){
i++;
}
}
int t;
t=a[i];
a[i]=a[j];
a[j]=t;
}
int t;
t=a[start];
a[start]=a[i];
a[i]=t;
pai(start,i-1,flag);
pai(j+1,end,flag);
}
int main(){
cin>>n;
for (int i=1;i<=n;i++){
cin>>a[i];
}
cin>>k;
pai(1,n,false);
cout<<a[k];
return 0;
}
归并排序(代码由adminh提供)
void sort_f(int x,int y){
if(x>=y)return ;
int m=(y-x>>1)+x;
sort_f(x,m);
sort_f(1+m,y);
for(int i=x;i<=y;i++)c[i]=a[i];
int k=x,l=m+1;
for(int i=x;i<=y;i++)
if(k<=m&&(l>y||c[k]<=c[l]))a[i]=c[k++];
else a[i]=c[l++],ans+=m-k+1;
}
搜索
深度优先搜索
图上深度优先搜索
#include <iostream>
#include <vector>
using namespace std;
vector<int> G[110];
bool vis[110];
void dfs(int u){
vis[u]=true;
cout<<u<<endl;
for (int i=0;i<G[u].size();i++){
int v=G[u][i];
if (!vis[v]){
dfs(v);
}
}
}
int main() {
int n, m;
cin >> n >> m;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1);
return 0;
}
求连通块数量
#include <iostream>
#include <vector>
using namespace std;
vector<int> G[110];
bool vis[110];
void dfs(int u) {
vis[u] = true;
for (int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if (!vis[v]) {
dfs(v);
}
}
}
int main() {
int n, m;
cin >> n >> m;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
int cnt=0;
for (int i=1;i<=n;i++){
if (!vis[i]){
cnt++;
dfs(i);
}
}
cout<<cnt<<endl;
return 0;
}
树上深度优先搜索
#include <iostream>
#include <vector>
using namespace std;
vector <int> G[105];
void dfs(int u, int fa) {
cout<<u<<endl;
for (int i=0;i<G[u].size();i++){
int v=G[u][i];
if (v!=fa){
dfs(v,u);
}
}
}
int main() {
int n;
cin >> n;
for (int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1,0);
return 0;
}
求树上节点的深度
#include <iostream>
#include <vector>
using namespace std;
vector<int> G[110];
int d[110];
void dfs(int u,int fa){
d[u]=d[fa]+1;
for (int i=0;i<G[u].size();i++){
int v=G[u][i];
if (v!=fa){
dfs(v,u);
}
}
}
int main() {
int n;
cin >> n;
for (int i = 0; i < n - 1; i++) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1,0);
for (int i=1;i<=n;i++){
cout<<i<<" "<<d[i]<<endl;
}
return 0;
}
求解子树大小
#include <iostream>
#include <vector>
using namespace std;
vector<int> G[110];
int sz[110];
int dfs(int u, int fa) {
for (int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if (v != fa) {
sz[u]+=dfs(v,u);
}
}
sz[u]++;
return sz[u];
}
int main() {
int n;
cin >> n;
for (int i = 0; i < n - 1; i++) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1, 0);
for (int i = 1; i <= n; i++) {
cout << i << " " << sz[i] << endl;
}
return 0;
}
枚举全排列
#include <iostream>
using namespace std;
const int N = 20;
int n;
int per[N];
bool vis[N];
void dfs (int dep) {
if (dep==n){
for (int i=0;i<n;i++){
cout<<per[i]<<" ";
}
cout<<endl;
return;
}
for (int i=1;i<=n;i++){
if (vis[i]){
continue;
}
per[dep]=i;
vis[i]=true;
dfs(dep+1);
vis[i]=false;
}
}
int main() {
cin >> n;
dfs(0);
return 0;
}
枚举K排列
#include <iostream>
using namespace std;
const int N = 20;
int n, k;
int per[N];
bool vis[N];
void dfs (int dep) {
if (dep == k) {
for (int i = 0; i < k; i++) {
cout << per[i] << " ";
}
cout << endl;
return;
}
for (int i = 1; i <= n; i++) {
if (vis[i]) {
continue;
}
per[dep] = i;
vis[i] = true;
dfs(dep + 1);
vis[i] = false;
}
}
int main() {
cin >> n >> k;
dfs(0);
return 0;
}
枚举组合
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 15;
int n, k;
int comb[N];
void dfs(int x, int dep) {
if (dep==k){
for (int i=0;i<k;i++){
cout<<comb[i]<<" ";
}
cout<<endl;
return;
}
if (x>n){
return;
}
comb[dep]=x;
dfs(x+1,dep+1);
dfs(x+1,dep);
}
int main() {
cin >> n >> k;
dfs(1,0);
return 0;
}
求n 个数中选k 个数使得和为sum 的方案数问题(去重版)
#include <iostream>
using namespace std;
int n, k, sum, ans;
int a[40];
bool xuan[40];
void dfs(int s,int cnt){
if (s==sum && cnt==k){
ans++;
}
for (int i=0;i<n;i++){
if (!xuan[i]){
xuan[i]=1;
dfs(s+a[i],cnt+1);
xuan[i]=0;
}
}
}
int main() {
cin >> n >> k >> sum;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
ans=0;
dfs(0,0);
for (int i=1;i<=k;i++){
ans/=i;
}
cout<<ans<<endl;
return 0;
}
求解八皇后问题
#include <iostream>
using namespace std;
int ans = 0;
bool row[10],x1[20],x2[20];
int v[10];
bool check(int i,int c){
return !row[i] && !x1[i+c] && !x2[i-c+8];
}
void dfs(int c){
if (c==8){
ans++;
for (int i=0;i<8;i++){
for (int j=0;j<8;j++){
if (v[j]==i){
cout<<"Q";
}
else{
cout<<".";
}
}
cout<<endl;
}
cout<<endl;
return;
}
for (int i=0;i<8;i++){
if (check(i,c)){
row[i]=x1[i+c]=x2[i-c+8]=true;
v[c]=i;
dfs(c+1);
row[i]=x1[i+c]=x2[i-c+8]=false;
// v[c]=-1;
}
}
}
int main() {
dfs(0);
cout<<ans<<endl;
return 0;
}
广度优先搜索
求无权图的最短路
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
int n, m;
vector<int> G[105];
queue<int> q;
int dis[105];
void bfs(int s) {
memset(dis,-1,sizeof(dis));
dis[s]=0;
q.push(s);
while (!q.empty()){
int now=q.front();
q.pop();
for (int i=0;i<G[now].size();i++){
int v=G[now][i];
if (dis[v]==-1){
dis[v]=dis[now]+1;
q.push(v);
}
}
}
}
int main() {
cin >> n >> m;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
bfs(1);
for (int i = 1; i <= n; i++) {
cout << dis[i] << endl;
}
return 0;
}
多起点的广度优先搜索
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
int n, m;
vector<int> G[105];
queue<int> q;
int dis[105];
void bfs() {
memset(dis, -1, sizeof(dis));
dis[1]=0;
q.push(1);
dis[5]=0;
q.push(5);
while (!q.empty()) {
int now = q.front();
q.pop();
for (int i = 0; i < G[now].size(); i++) {
int v = G[now][i];
if (dis[v] == -1) {
dis[v] = dis[now] + 1;
q.push(v);
}
}
}
}
int main() {
cin >> n >> m;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
bfs();
for (int i = 1; i <= n; i++) {
cout << dis[i] << endl;
}
return 0;
}
求每个点到终点的最短路
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
int n, m;
vector<int> G[105];
queue<int> q;
int dis[105];
int bfs(int s) {
memset(dis, -1, sizeof(dis));
dis[s] = 0;
q.push(s);
while (!q.empty()) {
int now = q.front();
q.pop();
for (int i = 0; i < G[now].size(); i++) {
int v = G[now][i];
if (dis[v] == -1) {
dis[v] = dis[now] + 1;
q.push(v);
}
}
}
}
int main() {
cin >> n >> m;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
G[v].push_back(u);
}
bfs(n);
for (int i = 1; i <= n; i++) {
cout << dis[i] << " ";
}
cout << endl;
return 0;
}
动态规划
求最大子段和
#include <iostream>
#include <algorithm>
using namespace std;
const int inf = 1000000000;
int a[105], dp[105], ans = -inf;
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i=1;i<=n;i++){
if (dp[i-1]>=0){
dp[i]=dp[i-1]+a[i];
}
else{
dp[i]=a[i];
}
ans=max(ans,dp[i]);
}
cout<<ans;
return 0;
}
求最长上升子序列
#include <iostream>
#include <algorithm>
using namespace std;
int a[1005], dp[1005], ans;
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i=1;i<=n;i++){
dp[i]=1;
for (int j=1;j<i;j++){
if (a[j]<a[i]){
dp[i]=max(dp[i],dp[j]+1);
}
}
ans=max(ans,dp[i]);
}
cout<<ans;
return 0;
}
求最长公共子序列(LCS)
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int dp[1005][1005];
int main() {
string a, b;
cin >> a >> b;
for (int i=1;i<=a.size();i++){
for (int j=1;j<=b.size();j++){
if (a[i-1]==b[j-1]){
dp[i][j]=dp[i-1][j-1]+1;
}
else{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
cout<<dp[a.size()][b.size()];
return 0;
}
背包问题
01背包
未优化版
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[21][1010];
int w[21], c[21];
int main() {
int N, V;
cin >> N >> V;
for (int i = 1; i <= N; i++) {
cin >> w[i] >> c[i];
}
for (int i = 1; i <= N; i++) {
for (int j = 0; j <= V; j++) {
if (j >= c[i]) {
dp[i][j]=max(dp[i-1][j-c[i]]+w[i],dp[i-1][j]);
} else {
dp[i][j]=dp[i-1][j];
}
}
}
cout << dp[N][V] << endl;
return 0;
}
空间优化版
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[1010];
int w[21], c[21];
int main() {
int N, V;
cin >> N >> V;
for (int i = 1; i <= N; i++) {
cin >> w[i] >> c[i];
}
int flag = 1;
for (int i = 1; i <= N; i++) {
for (int j=V;j>=c[i];j--){
dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
}
}
cout<<dp[V];
return 0;
}
多重背包
未优化版
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[21][1010];
int w[21], c[21], n[21];
int main() {
int N, V;
cin >> N >> V;
for (int i = 1; i <= N; ++i) {
cin >> w[i] >> c[i] >> n[i];
}
for (int i=1;i<=N;i++){
for (int j=0;j<=V;j++){
for (int k=0;k<=n[i];k++){
if (j>=k*c[i]){
dp[i][j]=max(dp[i][j],dp[i-1][j-k*c[i]]+k*w[i]);
}
}
}
}
cout << dp[N][V] << endl;
return 0;
}
空间优化版
#include <iostream>
#include <cstring>
using namespace std;
int dp[1010];
int w[21], c[21], n[21];
int main() {
int N, V;
cin >> N >> V;
for (int i = 1; i <= N; i++) {
cin >> w[i] >> c[i] >> n[i];
}
for (int i = 1; i <= N; i++) {
for (int j=V;j>=0;j--) {
for (int k = 0; k <= n[i]; k++) {
if (j >= c[i] * k) {
dp[j] = max(dp[j - c[i] * k] + w[i] * k, dp[j]);
}
}
}
}
cout << dp[V] << endl;
return 0;
}
完全背包
未优化版
#include <iostream>
#include <cstring>
using namespace std;
int dp[21][1010];
int w[21], c[21];
int main() {
int N, V;
cin >> N >> V;
for (int i = 1; i <= N; i++) {
cin >> w[i] >> c[i];
}
for (int i=1;i<=N;i++){
for (int j=0;j<=V;j++){
if (j>=c[i]){
dp[i][j]=max(dp[i][j-c[i]]+w[i],dp[i-1][j]);
}
else{
dp[i][j]=dp[i-1][j];
}
}
}
cout << dp[N][V] << endl;
return 0;
}
空间优化版
#include <iostream>
using namespace std;
int dp[1010];
int w[21], c[21];
int main() {
int N, V;
cin >> N >> V;
for (int i = 1; i <= N; i++) {
cin >> w[i] >> c[i];
}
for (int i = 1; i <= N; i++) {
for (int j = c[i]; j <= V; j++) {
dp[j] = max(dp[j - c[i]] + w[i], dp[j]);
}
}
cout << dp[V] << endl;
return 0;
}
背包可行性判定
#include <iostream>
using namespace std;
bool dp[110][1010];
int c[110];
int main() {
int N, V;
cin >> N >> V;
for (int i = 1; i <= N; i++) {
cin >> c[i];
}
dp[0][0]=1;
for (int i=1;i<=N;i++){
for (int j=0;j<=V;j++){
if (j<c[i]){
dp[i][j]=dp[i-1][j];
}
else{
dp[i][j]=dp[i-1][j] || dp[i-1][j-c[i]];
}
}
}
if (dp[N][V]){
cout<<"Yes";
}
else{
cout<<"No";
}
return 0;
}
多维限制背包
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[1010][1010];
int v[21], w[21], c[21];
int main() {
int N, V, W;
cin >> N >> V >> W;
for (int i = 1; i <= N; i++) {
cin >> v[i] >> w[i] >> c[i];
}
for (int i = 1; i <= N; i++) {
for (int j = V; j >= v[i]; j--) {
for (int k = W; k >= w[i]; k--) {
dp[j][k]=max(dp[j][k],dp[j-v[i]][k-w[i]]+c[i]);
}
}
}
cout << dp[V][W] << endl;
return 0;
}
图论
链式前向星
struct Edge {//建结构体,maxm为题目要求的最大边数,maxn为题目要求的最大节点数
int to, next, dis;
} edge[maxm * 2];//无向图一定一定要*2,否则可能会导致丢分
int h[maxn], tot;
void addEdge(int x, int y, int len) {//建边
edge[++tot] = {y, h[x], len};
h[x] = tot;
}
for (int i = h[x]; i; i = edge[i].next) {//遍历边
// 以下省略一个地球
}
最短路
Floyd算法
#include <bits/stdc++.h>
using namespace std;
const int N = 101;
int g[N][N], n, m, u, v, w;;
int main() {
memset(g, 0x3f, sizeof(g));
for (int i = 0; i < N; i++) g[i][i] = 0;
cin >> n >> m;
for (int i = 0; i < m; i++) {
cin >> u >> v >> w;
g[u][v] = g[v][u] = w;
}
for (int k=1;k<=n;k++){
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cout << g[i][j] << " ";
}
cout << endl;
}
return 0;
}
dijkstra算法(堆优化版)
普通版
#include <bits/stdc++.h>
using namespace std;
const int N = 1001;
const int M = 10101;
const int inf = 0x3f3f3f3f;
struct Edge {
int to, next, len;
} e[M * 2];
int h[N], tot, n, m, s, d[N];
bool vis[N];
set<pair<int, int>> heap;
void addEdge(int x, int y, int len) {
e[++tot] = {y, h[x], len};
h[x] = tot;
}
void dijkstra(int s) {
memset(d, 0x3f, sizeof(d));
memset(vis, 0, sizeof(vis));
d[s] = 0;
heap.insert({0,s});
while (heap.size()){
int v=heap.begin()->second;
heap.erase(heap.begin());
for (int i=h[v];i;i=e[i].next){
int to=e[i].to;
if (d[to]>d[v]+e[i].len){
heap.erase({d[to],to});
d[to]=d[v]+e[i].len;
heap.insert({d[to],to});
}
}
}
}
int main() {
cin >> n >> m >> s;
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
addEdge(u, v, w);
addEdge(v, u, w);
}
dijkstra(s);
for (int i = 1; i <= n; i++) {
cout << d[i] << " ";
}
return 0;
}
优先队列版(代码由Scez提供)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=100050,M=500050;
int n,m,s;
int u,v,w;
struct edge{
int to,next,w;
}e[M];
int head[N],cnt;
int dis[N];
struct node{
int dis,id;
bool operator <(const node &x)const
{
return x.dis<dis;
}
};
void add(int u,int v,int w)
{
cnt++;
e[cnt].to=v;
e[cnt].next=head[u];
e[cnt].w=w;
head[u]=cnt;
}
priority_queue<node> q;
int vis[N];
void dij()
{
q.push((node){0,s});
for(int i=2;i<=n;i++)
dis[i]=0x3f3f3f3f;
while(!q.empty())
{
node now=q.top();
q.pop();
if(vis[now.id])
continue;
vis[now.id]=1;
for(int i=head[now.id];i;i=e[i].next)
{
int p=e[i].to;
if(dis[p]>dis[now.id]+e[i].w)
{
dis[p]=dis[now.id]+e[i].w;
if(!vis[p])
q.push((node){dis[p],p});
}
}
}
}
int main()
{
cin>>n>>m>>s;
while(m--)
{
cin>>u>>v>>w;
add(u,v,w);
}
dij();
for(int i=1;i<=n;i++)
{
cout<<dis[i]<<" ";
}
return 0;
}
SPFA算法
#include <bits/stdc++.h>
using namespace std;
const int N = 1001;
const int M = 10101;
const int inf = 0x3f3f3f3f;
struct Edge {
int to, next, len;
} e[M * 2];
int h[N], tot, n, m, s, d[N], inq[N];
queue<int> q;
void addEdge(int x, int y, int len) {
e[++tot] = {y, h[x], len};
h[x] = tot;
}
void spfa(int s) {
memset(d, 0x3f, sizeof(d));
memset(inq, 0, sizeof(inq));
d[s] = 0;
inq[s]=true;
q.push(s);
while (!q.empty()){
int v=q.front();
q.pop();
inq[v]=false;
for (int i=h[v];i;i=e[i].next){
int to=e[i].to;
if (d[to]>d[v]+e[i].len){
d[to]=d[v]+e[i].len;
if (!inq[to]){
q.push(to);
inq[to]=true;
}
}
}
}
}
int main() {
cin >> n >> m >> s;
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
addEdge(u, v, w);
addEdge(v, u, w);
}
spfa(s);
for (int i = 1; i <= n; i++) {
cout << d[i] << " ";
}
return 0;
}
并查集(路径压缩后)
#include <iostream>
using namespace std;
int fa[110];
int n, m;
void init() {//初始化fa数组
for (int i = 1; i <= n; i++) {
fa[i] = i;
}
}
int get(int x) {//查找x所在集合的代表
if (fa[x] == x) {
return x;
}
fa[x]=get(fa[x]);//路径压缩
return fa[x];
}
void merge(int x, int y) {//合并x所在的集合和y所在的集合
x = get(x);
y = get(y);
if (x != y) {
fa[y] = x;
}
}
int main() {
cin >> n >> m;
init();
for (int i = 0; i < m; i++) {
int a, b;
cin >> a >> b;
merge(a, b);
}
int cnt = 0;
for (int i = 1; i <= n; i++) {
if (fa[i]==i) {
cnt++;
}
}
cout << cnt << endl;
return 0;
}
最小生成树
kruskal算法
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1100; // 最大顶点数
const int M = 100100; // 最大边数
struct Edge {// 使用结构体储存每一条边,便于排序
int u, v, w; // 表示有一条 (u,v) 的无向边,边权为 w
} e[M];
int ecnt;// 用于边表计数
void addEdge(int u, int v, int w){ // 加入一条无向边
e[++ecnt] = {u, v, w};
}
int fa[N]; // 并查集相关
int find(int x) {
return x == fa[x] ? x : fa[x] = find(fa[x]); // 路径压缩
}
int n; // 顶点数
bool cmp(const Edge &a, const Edge &b){
return a.w < b.w;
}
int Kruskal() { // Kruskal 算法核心过程
for (int i = 1; i <= n; i++) {
fa[i] = i; // 初始化并查集
}
sort(e+1,e+ecnt+1,cmp);
int sum=0,cnt=0;
for (int i=1;i<=ecnt;i++){
int u=e[i].u,v=e[i].v;
u=find(u);
v=find(v);
if (u!=v){
fa[u]=v;
sum+=e[i].w;
cnt++;
}
}
if (cnt!=n-1){
return -1;
}
return sum;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
int w;
cin >> w;
addEdge(i, j, w);
}
}
cout << Kruskal();
return 0;
}
prim算法
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 1001;
const int maxm = 10101;
const int inf = 0x3f3f3f3f;
struct Edge {
int to, next, len;
} edge[maxm * 2];
int h[maxn], tot = -1;
int n, m, s;
int d[maxn];
bool vis[maxn];
void addEdge(int x, int y, int len) {
edge[++tot] = {y, h[x], len};
h[x] = tot;
}
int prim() {
memset(d, 0x3f, sizeof(d));
d[s] = 0;
int sum = 0;
for (int i = 1; i <= n; i++) {
int mind = inf;
int v = 0;
for (int j = 1; j <= n; j++) {
if (!vis[j] && d[j] < mind) {
mind = d[j];
v = j;
}
}
if (mind == inf) {
break;
}
vis[v] = true;
sum += d[v];
for (int j = h[v]; j != -1; j = edge[j].next) {
int to = edge[j].to;
d[to] = min(d[to], edge[j].len);
}
}
return sum;
}
int main() {
cin >> n >> m >> s;
memset(h, -1, sizeof(h));
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
addEdge(u, v, w);
addEdge(v, u, w);
}
cout << prim() << endl;
return 0;
}
求树的重心
#include <iostream>
using namespace std;
const int N = 50010; // 结点个数
struct Edge { // 临接表储存
int to, next;
} G[2 * N]; // 无向边,所以需要开双倍的边表
int head[N], ecnt;// 用于边表计数
void addEdge(int u, int v) {
G[++ecnt] = {v, head[u]};
head[u] = ecnt;
}
int n;
int siz[N],f[N];
void dfs(int u,int fa){
siz[u]=1;
f[u]=0;
for (int i=head[u];i;i=G[i].next){
int v=G[i].to;
if (v==fa){
continue;
}
dfs(v,u);
siz[u]+=siz[v];
f[u]=max(f[u],siz[v]);
}
f[u]=max(f[u],n-siz[u]);
}
int main() {
cin >> n;
int u, v;
for (int i = 1; i < n; i++) {
cin >> u >> v; // 读入树
addEdge(u, v); // 无向边插入两次
addEdge(v, u);
}
int id = 1;
dfs(1,1);
for (int i = 2; i <= n; i++) {
if (f[i] < f[id]) {
id = i;
}
}
cout << id << " " << f[id] << endl;
return 0;
}
求树的直径
#include <iostream>
using namespace std;
const int N = 50010;
struct Edge{
int to, next;
} G[2 * N];
int head[N], ecnt;
void addEdge(int u, int v) {
G[++ecnt] = {v, head[u]};
head[u] = ecnt;
}
int len, id;
void dfs(int u, int fa, int dis) {
if (dis > len) {
len = dis;
id = u;
}
for (int i=head[u];i;i=G[i].next){
int v=G[i].to;
if (v==fa){
continue;
}
dfs(v,u,dis+1);
}
}
int main() {
int n;
cin >> n;
int u, v;
for (int i = 1; i < n; i++) {
cin >> u >> v; // 读入树
addEdge(u, v); // 无向边插入两次
addEdge(v, u);
}
len=0;
id=1;
dfs(1,1,0);
int x=id;
len=0;
id=x;
dfs(x,x,0);
cout<<len;
return 0;
}
拓扑排序
非字典序最小版
#include <bits/stdc++.h>
using namespace std;
const int maxn = 10010;
const int maxm = 100010;
vector<int> G[maxn];
int rd[maxn];
void addEdge(int u, int v) {
G[u].push_back(v);
rd[v]++;
}
int seq[maxn];
bool toposort(int n) {
queue<int> q;
for (int i=1;i<=n;i++){
if (rd[i]==0){
q.push(i);
}
}
int ncnt=0;
while (!q.empty()){
int u=q.front();
q.pop();
seq[++ncnt]=u;
for (int i=0;i<G[u].size();i++){
int v=G[u][i];
rd[v]--;
if (rd[v]==0){
q.push(v);
}
}
}
return ncnt==n;
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
int u, v;
for (int i = 1; i <= m; i++) {
scanf("%d%d", &u, &v);
addEdge(u, v);
}
if (!toposort(n)) {
puts("Not DAG");
} else {
for (int i = 1; i <= n; i++) {
printf("%d%c", seq[i], i == n ? '\n' : ' ');
}
}
return 0;
}
字典序最小版
#include <bits/stdc++.h>
using namespace std;
const int maxn = 10010;
const int maxm = 100010;
vector <int> G[maxn];
int deg[maxn];
void addEdge(int u, int v) {
G[u].push_back(v);
deg[v]++;
}
int seq[maxn];
bool toposort(int n) {
priority_queue<int,vector<int>,greater<int>> q;
for (int i = 1; i <= n; i++) {
if (deg[i] == 0) {
q.push(i);
}
}
int ncnt = 0;
while (!q.empty()) {
int u = q.top();
q.pop();
seq[++ncnt] = u;
for (int i = 0; i < G[u].size(); i++){
int v = G[u][i];
deg[v] -= 1;
if(deg[v] == 0) {
q.push(v);
}
}
}
return ncnt == n;
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
int u, v;
for (int i = 1; i <= m; i++) {
scanf("%d%d", &u, &v);
addEdge(u, v);
}
if (!toposort(n)) {
puts("Not DAG");
} else {
for (int i = 1; i <= n; i++) {
printf("%d%c", seq[i], i == n ? '\n' : ' ');
}
}
return 0;
}
求解欧拉路径
#include <bits/stdc++.h>
using namespace std;
struct node {
int v, id;
};
vector<node> G[105];
int fa[105], in[105], out[105];
int n, m, f, cntout, cntin, start;
stack<int> s;
bool vis[10005];
void init() {
for (int i = 1; i <= n; i++) {
fa[i] = i;
}
}
int get(int x) {
if (fa[x] == x) {
return x;
}
return fa[x] = get(fa[x]);
}
void merge(int x, int y) {
x = get(x);
y = get(y);
if (x != y) {
fa[y] = x;
f--;
}
}
int euler() {
for (int i = 1; i <= n; i++) {
if (out[i] == 0 && in[i] == 0) {
f--;
}
}
if (f != 1) {
return 0;
}
for (int i = 1; i <= n; i++) {
if (out[i] - in[i] == 1) {
cntout++;
} else if (out[i] - in[i] == -1) {
cntin++;
} else if (out[i] != in[i]) {
return 0;
}
}
if (cntout == 0 && cntin == 0) {
return 1;
} else if (cntout == 1 && cntin == 1) {
for (int i = 1; i <= n; i++) {
if (out[i] - in[i] == 1) {
return i;
}
}
} else {
return 0;
}
}
void dfs(int u) {
if (out[u]){
for (int i=0;i<G[u].size();i++){
if (!vis[G[u][i].id]){
vis[G[u][i].id]=true;
out[u]--;
dfs(G[u][i].v);
}
}
}
s.push(u);
}
int main() {
cin >> n >> m;
init();
f = n;
for (int i = 1; i <= m; i++) {
int u, v;
cin >> u >> v;
G[u].push_back({v, i});
merge(u, v);
out[u]++;
in[v]++;
}
start = euler();
if (start) {
dfs(start);
while (!s.empty()){
cout<<s.top()<<endl;
s.pop();
}
} else {
cout << "No" << endl;
}
return 0;
}
注:这份代码多了判断图是否连通的部分,如果题目中保证图是连通的,可以省去很多代码
最近公共祖先(LCA)
#include <cstring>
#include <iostream>
using namespace std;
const int MAX_N = 100005;
const int MAX_M = 200005;
struct Edge {
int v, next;
} e[MAX_M];
int p[MAX_N], eid;
void init() {
memset(p, -1, sizeof(p));
eid = 0;
}
void insert(int u, int v) {
e[eid].v = v;
e[eid].next = p[u];
p[u] = eid++;
}
int f[MAX_N][20], d[MAX_N];
void dfs(int u) {
d[u]=d[f[u][0]]+1;
for (int i = p[u]; i != -1; i = e[i].next) {
int v = e[i].v;
if (v == f[u][0]) {
continue;
}
f[v][0]=u;
dfs(v);
}
}
int lca(int x,int y){
if (d[x]<d[y]){
swap(x,y);
}
int K=0;
while ((1<<(K+1))<=d[x]){
K++;
}
for (int j=K;j>=0;j--){
if (d[f[x][j]]>=d[y]){
x=f[x][j];
}
}
if (x==y){
return x;
}
for (int j=K;j>=0;j--){
if (f[x][j]!=f[y][j]){
x=f[x][j];
y=f[y][j];
}
}
return f[x][0];
}
int main() {
int n, q;
cin >> n >> q;
init();
for (int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
insert(u, v);
insert(v, u);
}
dfs(1);
for (int j=1;(1<<j)<=n;j++){
for (int i=1;i<=n;i++){
f[i][j]=f[f[i][j-1]][j-1];
}
}
while (q--) {
int x, y;
cin >> x >> y;
cout << lca(x, y) << endl;
}
return 0;
}
进制转换
任意进制转十进制
#include <iostream>
#include <cmath>
using namespace std;
int main(){
int a;
cin>>a;
int b[100];
string n[100];
for (int i=1;i<=a;i++){
cin>>b[i]>>n[i];
}
for (int i=1;i<=a;i++){
int jieguo=0;
for (int j=n[i].size()-1;j>=0;j--){
if (n[i][j]=='A'){
jieguo+=10*pow(b[i],n[i].size()-1-j);
}
else if (n[i][j]=='B'){
jieguo+=11*pow(b[i],n[i].size()-1-j);
}
else if (n[i][j]=='C'){
jieguo+=12*pow(b[i],n[i].size()-1-j);
}
else if (n[i][j]=='D'){
jieguo+=13*pow(b[i],n[i].size()-1-j);
}
else if (n[i][j]=='E'){
jieguo+=14*pow(b[i],n[i].size()-1-j);
}
else if (n[i][j]=='F'){
jieguo+=15*pow(b[i],n[i].size()-1-j);
}
else{
jieguo+=(n[i][j]-'0')*pow(b[i],n[i].size()-1-j);
}
}
cout<<jieguo<<endl;
}
return 0;
}
十进制转任意进制
#include <iostream>
#include <cstring>
using namespace std;
int main(){
int b[100];
int n[100];
int a;
cin>>a;
for (int i=1;i<=a;i++){
cin>>b[i]>>n[i];
}
for (int i=1;i<=a;i++){
string jieguo;
int j=1;
while (n[i]>=b[i]){
int c=n[i]%b[i];
if (c==10){
jieguo[j]='A';
}
else if (c==11){
jieguo[j]='B';
}
else if (c==12){
jieguo[j]='C';
}
else if (c==13){
jieguo[j]='D';
}
else if (c==14){
jieguo[j]='E';
}
else if (c==15){
jieguo[j]='F';
}
else{
jieguo[j]=c+'0';
}
n[i]=n[i]/b[i];
j++;
}
if (n[i]==10){
jieguo[j]='A';
}
else if (n[i]==11){
jieguo[j]='B';
}
else if (n[i]==12){
jieguo[j]='C';
}
else if (n[i]==13){
jieguo[j]='D';
}
else if (n[i]==14){
jieguo[j]='E';
}
else if (n[i]==15){
jieguo[j]='F';
}
else{
jieguo[j]=n[i]+'0';
}
for (int k=j;k>=1;k--){
cout<<jieguo[k];
}
cout<<endl;
}
return 0;
}
高精度
高精度加法
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main(){
string a1,b1;
int a[10000],b[10000],c[10000],lena,lenb,lenc,i,x=0;
cin>>a1>>b1;
lena=a1.length();
lenb=b1.length();
for (int i=0;i<lena;i++){
a[lena-i]=a1[i]-48;
}
for (int i=0;i<lenb;i++){
b[lenb-i]=b1[i]-48;
}
lenc=0;
while (lenc<=lena||lenc<=lenb){
c[lenc]=a[lenc]+b[lenc]+x;
if (c[lenc]>=10){
c[lenc]=c[lenc]%10;
c[lenc+1]=1;
x=1;
}
else{
x=0;
}
lenc++;
}
if (a[lenc]==0){
lenc--;
}
for (int i=lenc;i>=1;i--){
cout<<c[i];
}
return 0;
}
高精度计算器(来自OI Wiki)
#include <cstdio>
#include <cstring>
static const int LEN = 1004;
int a[LEN], b[LEN], c[LEN], d[LEN];
void clear(int a[]) {
for (int i = 0; i < LEN; ++i) a[i] = 0;
}
void read(int a[]) {
static char s[LEN + 1];
scanf("%s", s);
clear(a);
int len = strlen(s);
for (int i = 0; i < len; ++i) a[len - i - 1] = s[i] - '0';
}
void print(int a[]) {
int i;
for (i = LEN - 1; i >= 1; --i)
if (a[i] != 0) break;
for (; i >= 0; --i) putchar(a[i] + '0');
putchar('\n');
}
void add(int a[], int b[], int c[]) {
clear(c);
for (int i = 0; i < LEN - 1; ++i) {
c[i] += a[i] + b[i];
if (c[i] >= 10) {
c[i + 1] += 1;
c[i] -= 10;
}
}
}
void sub(int a[], int b[], int c[]) {
clear(c);
for (int i = 0; i < LEN - 1; ++i) {
c[i] += a[i] - b[i];
if (c[i] < 0) {
c[i + 1] -= 1;
c[i] += 10;
}
}
}
void mul(int a[], int b[], int c[]) {
clear(c);
for (int i = 0; i < LEN - 1; ++i) {
for (int j = 0; j <= i; ++j) c[i] += a[j] * b[i - j];
if (c[i] >= 10) {
c[i + 1] += c[i] / 10;
c[i] %= 10;
}
}
}
bool greater_eq(int a[], int b[], int last_dg, int len) {
if (a[last_dg + len] != 0) return true;
for (int i = len - 1; i >= 0; --i) {
if (a[last_dg + i] > b[i]) return true;
if (a[last_dg + i] < b[i]) return false;
}
return true;
}
void div(int a[], int b[], int c[], int d[]) {
clear(c);
clear(d);
int la, lb;
for (la = LEN - 1; la > 0; --la)
if (a[la - 1] != 0) break;
for (lb = LEN - 1; lb > 0; --lb)
if (b[lb - 1] != 0) break;
if (lb == 0) {
puts("> <");
return;
}
for (int i = 0; i < la; ++i) d[i] = a[i];
for (int i = la - lb; i >= 0; --i) {
while (greater_eq(d, b, i, lb)) {
for (int j = 0; j < lb; ++j) {
d[i + j] -= b[j];
if (d[i + j] < 0) {
d[i + j + 1] -= 1;
d[i + j] += 10;
}
}
c[i] += 1;
}
}
}
int main() {
read(a);
char op[4];
scanf("%s", op);
read(b);
switch (op[0]) {
case '+':
add(a, b, c);
print(c);
break;
case '-':
sub(a, b, c);
print(c);
break;
case '*':
mul(a, b, c);
print(c);
break;
case '/':
div(a, b, c, d);
print(c);
print(d);
break;
default:
puts("> <");
}
return 0;
}
其它
判断是否是质数
bool isprime(int a){
if (a<=1){
return false;
}
for (int i=2;i*i<=a;i++){
if (a%i==0){
return false;
}
}
return true;
}
两数的最大公约数
int gcd(int a,int b){
if (b==0){
return a;
}
return gcd(b,a%b);
}
后续正在施工中,敬请期待!
如果您还有其他模板,但此处没有,可以评论或者私信我,我都会加上的
编写不易,给个点赞+关注支持一下,多谢!
感谢用户Scez、adminh提供了部分代码
本文总计字符数: