#include<bits/stdc++.h>usingnamespace std;constint N =510;int n, m;int g[N][N], dist[N];bool st[N];// 集合Svoiddijkstra(){memset(dist,0x3f,sizeof dist);
dist[1]=0;for(int i =0; i < n; i++){int t =-1;for(int j =1; j <= n; j++){if(!st[j]&&(t ==-1|| dist[j]< dist[t]))
t = j;}for(int j =1; j <= n; j++)
dist[j]=min(dist[j], dist[t]+ g[t][j]);
st[t]=true;}}intmain(){
cin >> n >> m;memset(g,0x3f,sizeof g);for(int i =0; i < m; i++){int a, b, c;
cin >> a >> b >> c;
g[a][b]=min(g[a][b], c);}dijkstra();if(dist[n]==0x3f3f3f3f) cout <<-1<< endl;else cout << dist[n]<< endl;return0;}
堆优化 Dijkstra 算法的代码实现
#include<bits/stdc++.h>usingnamespace std;typedef pair<int,int> PII;constint N =2e5+10;int n, m;int h[N], e[N], w[N], ne[N], idx;int dist[N];bool st[N];voidadd(int a,int b,int c){
e[idx]= b, w[idx]= c, ne[idx]= h[a], h[a]= idx++;}voiddijkstra(){memset(dist,0x3f,sizeof dist);
dist[1]=0;
priority_queue<PII, vector<PII>, greater<PII>> pq;
pq.push({0,1});while(!pq.empty()){auto[_, t]= pq.top(); pq.pop();// 此处不可以用引用if(st[t])continue;for(int i = h[t]; i !=-1; i = ne[i]){int j = e[i];if(dist[j]> dist[t]+ w[i]){
dist[j]= dist[t]+ w[i];
pq.push({dist[j], j});}}
st[t]=true;}}intmain(){
cin >> n >> m;memset(h,-1,sizeof h);for(int i =0; i < m; i++){int a, b, c;
cin >> a >> b >> c;add(a, b, c);}dijkstra();if(dist[n]==0x3f3f3f3f) cout <<-1<< endl;else cout << dist[n]<< endl;return0;}
Bellman-Ford 算法的代码实现
#include<bits/stdc++.h>usingnamespace std;constint N =510, M =1e4+10;int n, m, k;int dist[N], last[N];structEdge{int a, b, w;}edges[M];voidbellman_ford(){memset(dist,0x3f,sizeof dist);
dist[1]=0;for(int i =0; i < k; i++){memcpy(last, dist,sizeof dist);for(int j =0; j < m; j++){int a = edges[j].a, b = edges[j].b, w = edges[j].w;
dist[b]=min(dist[b], last[a]+ w);}}}intmain(){
cin >> n >> m >> k;for(int i =0; i < m; i++){int a, b, c;
cin >> a >> b >> c;
edges[i]={a, b, c};}bellman_ford();if(dist[n]>0x3f3f3f3f/2) cout <<"impossible"<< endl;else cout << dist[n]<< endl;return0;}
SPFA 算法的代码实现
#include<bits/stdc++.h>usingnamespace std;constint N =1e5+10;int n, m;int h[N], e[N], w[N], ne[N], idx;int dist[N];bool st[N];// 标记某个点是否已在队列中voidadd(int a,int b,int c){
e[idx]= b, w[idx]= c, ne[idx]= h[a], h[a]= idx++;}voidspfa(){memset(dist,0x3f,sizeof dist);
dist[1]=0;
queue<int> que;
que.push(1);
st[1]=true;while(!que.empty()){auto t = que.front(); que.pop();
st[t]=false;// 标记t已不在队列中for(int i = h[t]; i !=-1; i = ne[i]){int j = e[i];if(dist[j]> dist[t]+ w[i]){
dist[j]= dist[t]+ w[i];if(!st[j]){
st[j]=true;
que.push(j);}}}}}intmain(){
cin >> n >> m;memset(h,-1,sizeof h);for(int i =0; i < m; i++){int a, b, c;
cin >> a >> b >> c;add(a, b, c);}spfa();if(dist[n]==0x3f3f3f3f) cout <<"impossible"<< endl;else cout << dist[n]<< endl;return0;}
SPFA 判负环的代码实现
#include<bits/stdc++.h>usingnamespace std;constint N =2010, M =1e4+10;int n, m;int h[N], e[M], w[M], ne[M], idx;int dist[N], cnt[N];bool st[N];voidadd(int a,int b,int c){
e[idx]= b, w[idx]= c, ne[idx]= h[a], h[a]= idx++;}boolspfa(){
queue<int> que;for(int i =1; i <= n; i++){
que.push(i);
st[i]=true;}while(!que.empty()){auto t = que.front(); que.pop();
st[t]=false;for(int i = h[t]; i !=-1; i = ne[i]){int j = e[i];if(dist[j]> dist[t]+ w[i]){
dist[j]= dist[t]+ w[i];
cnt[j]= cnt[t]+1;if(cnt[j]>= n)returntrue;if(!st[j]){
que.push(j);
st[j]=true;}}}}returnfalse;}intmain(){
cin >> n >> m;memset(h,-1,sizeof h);for(int i =0; i < m; i++){int a, b, c;
cin >> a >> b >> c;add(a, b, c);}if(spfa()) cout <<"Yes"<< endl;else cout <<"No"<< endl;return0;}
Floyd 算法的代码实现
#include<bits/stdc++.h>usingnamespace std;constint N =210;int n, m, q;int d[N][N];voidfloyd(){for(int k =1; k <= n; k++){for(int i =1; i <= n; i++){for(int j =1; j <= n; j++){
d[i][j]=min(d[i][j], d[i][k]+ d[k][j]);}}}}intmain(){
cin >> n >> m >> q;memset(d,0x3f,sizeof d);for(int i =1; i <= n; i++) d[i][i]=0;for(int i =0; i < m; i++){int a, b, c;
cin >> a >> b >> c;
d[a][b]=min(d[a][b], c);}floyd();for(int i =0; i < q; i++){int a, b;
cin >> a >> b;if(d[a][b]>0x3f3f3f3f/2) cout <<"impossible"<< endl;else cout << d[a][b]<< endl;}return0;}
Prim 算法求最小生成树
#include<bits/stdc++.h>usingnamespace std;constint N =510, INF =0x3f3f3f3f;int n, m;int g[N][N], dist[N];bool st[N];intprim(){memset(dist,0x3f,sizeof dist);int res =0;for(int i =0; i < n; i++){int t =-1;for(int j =1; j <= n; j++){if(!st[j]&&(t ==-1|| dist[j]< dist[t]))
t = j;}if(i && dist[t]== INF)return INF;if(i) res += dist[t];for(int j =1; j <= n; j++){
dist[j]=min(dist[j], g[t][j]);}
st[t]=true;}return res;}intmain(){
cin >> n >> m;memset(g,0x3f,sizeof g);for(int i =0; i < m; i++){int a, b, c;
cin >> a >> b >> c;
g[a][b]= g[b][a]=min(g[a][b], c);// 无向图需要添加两条有向边}int t =prim();if(t == INF) cout <<"impossible"<< endl;else cout << t << endl;return0;}
Kruskal 算法求最小生成树
#include<bits/stdc++.h>usingnamespace std;constint N =1e5+10, M = N *2, INF =0x3f3f3f3f;int n, m;int p[N];structEdge{int a, b, w;booloperator<(const Edge& e){return w < e.w;}}edges[M];intfind(int x){if(p[x]!= x) p[x]=find(p[x]);return p[x];}intkruskal(){sort(edges, edges + m);for(int i =1; i <= n; i++) p[i]= i;// 初始化并查集int res =0, cnt =0;// res是当前最小生成树的总长度,cnt是当前最小生成树的总边数for(int i =0; i < m; i++){int a = edges[i].a, b = edges[i].b, w = edges[i].w;
a =find(a), b =find(b);if(a != b){
p[a]= b;
res += w;
cnt++;}}if(cnt == n -1)return res;elsereturn INF;}intmain(){
cin >> n >> m;for(int i =0; i < m; i++){int a, b, c;
cin >> a >> b >> c;
edges[i]={a, b, c};}int t =kruskal();if(t == INF) cout <<"impossible"<< endl;else cout << t << endl;return0;}
染色法判定二分图
#include<bits/stdc++.h>usingnamespace std;constint N =1e5+10, M = N *2;// 无向图边数为点数的2倍int n, m;int h[N], e[M], ne[M], idx;int color[N];voidadd(int a,int b){
e[idx]= b, ne[idx]= h[a], h[a]= idx++;}booldfs(int u,int c){// 尝试将节点u染成颜色c
color[u]= c;for(int i = h[u]; i !=-1; i = ne[i]){int j = e[i];if(!color[j]){if(!dfs(j,3- c))returnfalse;// 若为子节点染色失败,则返回false}elseif(color[j]== c)returnfalse;// 若子节点已染色但和当前节点所染颜色一样,则返回false}returntrue;// 若整个连通块均染色顺利,则说明当前连通块是二分图}intmain(){
cin >> n >> m;memset(h,-1,sizeof h);for(int i =0; i < m; i++){int a, b;
cin >> a >> b;add(a, b),add(b, a);// 无向图要添加两条有向边}bool flag =true;for(int i =1; i <= n; i++){if(!color[i]){if(!dfs(i,1)){// 若没有染色成功,则说明不是二分图,应置flag为false,并立即退出
flag =false;break;}}}if(flag) cout <<"Yes"<< endl;else cout <<"No"<< endl;return0;}
匈牙利算法求二分图的最大匹配
#include<bits/stdc++.h>usingnamespace std;constint N =510, M =1e5+10;int n1, n2, m;int h[N], e[M], ne[M], idx;int match[N];bool st[N];voidadd(int a,int b){
e[idx]= b, ne[idx]= h[a], h[a]= idx++;}boolfind(int x){// 为左半部的点x寻找能够匹配的邻居。若能找到,则返回true;否则,返回falsefor(int i = h[x]; i !=-1; i = ne[i]){// 遍历x的所有邻居int j = e[i];if(!st[j]){// 如果该邻居尚未被之前的点考虑过,则
st[j]=true;// 考虑该邻居(不管后面有没有匹配成功,都要将j标记为“已考虑过”)if(match[j]==0||find(match[j])){// 若该邻居尚未被匹配,或能为匹配该邻居的点找到新的邻居,则
match[j]= x;// 让该邻居匹配点xreturntrue;// 返回匹配成功}}}returnfalse;// 若遍历完所有邻居都未能匹配,则匹配失败}intmain(){
cin >> n1 >> n2 >> m;memset(h,-1,sizeof h);for(int i =0; i < m; i++){int a, b;
cin >> a >> b;add(a, b);}int res =0;for(int i =1; i <= n1; i++){memset(st,false,sizeof st);if(find(i)) res++;// find函数的功能是为点i寻找能够匹配的邻居}
cout << res << endl;return0;}
有向图的拓扑序
#include<bits/stdc++.h>usingnamespace std;constint N =1e5+10;int n, m;int h[N], e[N], ne[N], idx;int ind[N];voidadd(int a,int b){
e[idx]= b, ne[idx]= h[a], h[a]= idx++;}
vector<int>top_sort(){/* 初始时,将所有入度为0的点加入队列 */
queue<int> que;for(int i =1; i <= n; i++){if(ind[i]==0) que.push(i);}
vector<int> res;while(!que.empty()){auto t = que.front(); que.pop();
res.push_back(t);for(int i = h[t]; i !=-1; i = ne[i]){int j = e[i];
ind[j]--;if(ind[j]==0) que.push(j);}}return res;}intmain(){
cin >> n >> m;memset(h,-1,sizeof h);for(int i =0; i < m; i++){int a, b;
cin >> a >> b;add(a, b);
ind[b]++;}auto t =top_sort();if(t.size()== n){for(auto x : t) cout << x <<" ";
cout << endl;}else cout <<-1<< endl;return0;}
快速排序
#include<bits/stdc++.h>usingnamespace std;constint N =1e5+10;int n;int a[N];voidquick_sort(int a[],int l,int r){if(l >= r)return;int x = a[l + r >>1];int i = l -1, j = r +1;while(i < j){do i++;while(a[i]< x);do j--;while(a[j]> x);if(i < j)swap(a[i], a[j]);}quick_sort(a, l, j);quick_sort(a, j +1, r);}intmain(){
cin >> n;for(int i =0; i < n; i++) cin >> a[i];quick_sort(a,0, n -1);for(int i =0; i < n; i++) cout << a[i]<<" ";
cout << endl;return0;}
归并排序
#include<bits/stdc++.h>usingnamespace std;constint N =1e5+10;int n;int a[N], tmp[N];voidmerge_sort(int a[],int l,int r){if(l >= r)return;int mid = l + r >>1;merge_sort(a, l, mid);merge_sort(a, mid +1, r);int i = l, j = mid +1, k =0;while(i <= mid && j <= r){if(a[i]<= a[j]) tmp[k++]= a[i++];else tmp[k++]= a[j++];}while(i <= mid) tmp[k++]= a[i++];while(j <= r) tmp[k++]= a[j++];for(int i = l, j =0; i <= r; i++, j++) a[i]= tmp[j];}intmain(){
cin >> n;for(int i =0; i < n; i++) cin >> a[i];merge_sort(a,0, n -1);for(int i =0; i < n; i++) cout << a[i]<<" ";
cout << endl;return0;}