DFS
排列问题
#include<iostream>
using namespace std;
const int N = 10;
int path[N];
int state[N];
int n;
void dfs(int u)
{
if(u > n)
{
for(int i = 1; i <= n; i++)
cout << path[i] << " ";
cout << endl;
}
for(int i = 1; i <= n; i++)
{
if(!state[i])
{
path[u] = i;
state[i] = 1;
dfs(u + 1);
state[i] = 0;
}
}
}
int main()
{
cin >> n;
dfs(1);
}
n皇后问题
#include <iostream>
using namespace std;
const int N = 11;
char q[N][N];
bool dg[N * 2], udg[N * 2], cor[N];
int n;
void dfs(int r)
{
if(r == n)
{
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
cout << q[i][j];
cout << endl;
}
cout << endl;
return;
}
for(int i = 0; i < n; i++)
{
if(!cor[i] && !dg[i + r] && !udg[n - i + r])
{
q[r][i] = 'Q';
cor[i] = dg[i + r] = udg[n - i + r] = 1;
dfs(r + 1);
cor[i] = dg[i + r] = udg[n - i + r] = 0;
q[r][i] = '.';
}
}
}
int main()
{
cin >> n;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < n; j ++ )
q[i][j] = '.';
dfs(0);
return 0;
}
BFS
走迷宫问题
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 110;
int g[N][N];
int f[N][N];
int n, m;
void bfs(int a, int b)
{
queue<PII> q;
q.push({a, b});
f[0][0] = 0;
while(!q.empty())
{
PII start = q.front();
q.pop();
g[start.first][start.second] = 1;
int dx[4] = {0, 1, 0, -1}, dy[4] = {-1, 0, 1, 0};
for(int i = 0; i < 4; i++)
{
int x = start.first + dx[i], y = start.second + dy[i];
if(g[x][y] == 0)
{
g[x][y] = 1;
f[x][y] = f[start.first][start.second] + 1;
q.push({x, y});
}
}
}
cout << f[n][m];
}
int main()
{
memset(g, 1, sizeof(g));
cin >> n >>m;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
cin >> g[i][j];
}
}
bfs(1,1);
}
八数码问题
#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#include <queue>
using namespace std;
queue<string> q;
string s;
unordered_map<string, int> h;
int main()
{
for(int i = 1; i <= 9; i++)
{
char c;
cin >> c;
s += c;
}
h[s] = 0;
q.push(s);
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
while(!q.empty())
{
string t = q.front();
q.pop();
if(t == "12345678x")
{
cout << h[t] << endl;
return 0;
}
int pos = t.find('x');
int a = pos /3 , b = pos % 3 ;
int dist = h[t];
for(int i = 0; i < 4; i++)
{
int x = a + dx[i], y = b + dy[i];
if(x >= 0 && x <= 2 && y >= 0 && y <= 2)
{
swap(t[pos], t[3 * x + y]);
if(h.find(t) == h.end())
{
h[t] = dist + 1;
q.push(t);
}
swap(t[pos], t[3 * x + y]);
}
}
}
cout << -1;
return 0;
}
树和图的深度优先遍历
树的重心问题
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1e5 + 10;
const int M = 2 * N;
int h[N];
int e[M];
int ne[M];
int idx;
int n;
int ans = N;
bool st[N];
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int dfs(int u) {
int res = 0;
st[u] = true;
int sum = 1;
for (int i = h[u]; i != -1; i = ne[i]) {
int j = e[i];
if (!st[j]) {
int s = dfs(j);
res = max(res, s);
sum += s;
}
}
res = max(res, n - sum);
ans = min(res, ans);
return sum;
}
int main() {
memset(h, -1, sizeof h);
cin >> n;
for (int i = 0; i < n - 1; i++) {
int a, b;
cin >> a >> b;
add(a, b), add(b, a);
}
dfs(1);
cout << ans << endl;
return 0;
}
树和图的广度优先遍历
图中点的层次
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 100010;
int h[N],ne[N], e[N], idx;
int dist[N];
int st[N];
int n, m;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void bfs()
{
memset(dist, 0x3f, sizeof(dist));
dist[1] = 0;
queue<int> q;
q.push(1);
st[1] = 1;
while(q.size())
{
int t = q.front();
q.pop();
for(int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
if(!st[j])
{
dist[j] = dist[t] + 1;
q.push(j);
st[j] = 1;
}
}
}
}
int main()
{
cin >> n >>m;
memset(h, -1, sizeof h);
for(int i = 0; i < m; i++)
{
int a, b;
cin >> a >> b;
add(a, b);
}
bfs();
cout << (dist[n] == 0x3f3f3f3f ? -1 : dist[n]);
return 0;
}
拓扑排序
有向图的拓扑序列
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
int e[N], ne[N], idx;
int h[N];
int q[N], hh = 0, tt = -1;
int n, m;
int d[N];
void add(int a, int b){
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void topsort(){
for(int i = 1; i <= n; i++){
if(d[i] == 0)
q[++tt] = i;
}
while(tt >= hh){
int a = q[hh++];
for(int i = h[a]; i != -1; i = ne[i]){
int b = e[i];
d[b]--;
if(d[b] == 0)
q[++tt] = b;
}
}
if(tt == n - 1){
for(int i = 0; i < n; i++){
cout << q[i] << " ";
}
}
else
cout << -1;
}
int main(){
cin >> n >> m;
memset(h, -1, sizeof h);
while (m -- ){
int a, b;
cin >> a >> b;
d[b]++;
add(a, b);
}
topsort();
return 0;
}
Dijstra
Dijstra求最短路径I
#include<iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 510, M = 100010;
int h[N], e[M], ne[M], w[M], idx;
int state[N];
int dist[N];
int n, m;
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
void Dijkstra()
{
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 (!state[j] && (t == -1 || dist[j] < dist[t]))
t = j;
}
state[t] = 1;
for (int j = h[t]; j != -1; j = ne[j])
{
int i = e[j];
dist[i] = min(dist[i], dist[t] + w[j]);
}
}
}
int main()
{
memset(h, -1, sizeof(h));
cin >> n >> m;
while (m--)
{
int a, b, w;
cin >> a >> b >> w;
add(a, b, w);
}
Dijkstra();
if (dist[n] != 0x3f3f3f3f)
cout << dist[n];
else
cout << "-1";
}
Dijstra求最短路径II
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 1e6 + 10;
int n, m;
int h[N], w[N], e[N], ne[N], idx;
int dist[N];
bool st[N];
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
int dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
priority_queue<PII, vector<PII>, greater<PII>> heap;
heap.push({0, 1});
while (heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second, distance = t.first;
if (st[ver]) continue;
st[ver] = true;
for (int i = h[ver]; i != -1; i = ne[i])
{
int j = e[i];
if (dist[j] > dist[ver] + w[i])
{
dist[j] = dist[ver] + w[i];
heap.push({dist[j], j});
}
}
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
int main()
{
scanf("%d%d", &n, &m);
memset(h, -1, sizeof h);
while (m -- )
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
}
cout << dijkstra() << endl;
return 0;
}
bellman-ford
有边数限制的最短路
#include<iostream>
#include<cstring>
using namespace std;
const int N = 510, M = 10010;
struct Edge {
int a;
int b;
int w;
} e[M];
int dist[N];
int back[N];
int n, m, k;
int bellman_ford() {
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for (int i = 0; i < k; i++) {
memcpy(back, dist, sizeof dist);
for (int j = 0; j < m; j++) {
int a = e[j].a, b = e[j].b, w = e[j].w;
dist[b] = min(dist[b], back[a] + w);
}
}
if (dist[n] > 0x3f3f3f3f / 2) return -1;
else return dist[n];
}
int main() {
scanf("%d%d%d", &n, &m, &k);
for (int i = 0; i < m; i++) {
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
e[i] = {a, b, w};
}
int res = bellman_ford();
if (res == -1) puts("impossible");
else cout << res;
return 0;
}
spfa
spfa求最短路
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 100010;
int h[N], e[N], w[N], ne[N], idx;
int st[N];
int dist[N];
int q[N], hh, tt = -1;
void add(int a, int b, int c){
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
void spfa(){
q[++tt] = 1;
dist[1] = 0;
st[1] = 1;
while(tt >= hh){
int a = q[hh++];
st[a] = 0;
for(int i = h[a]; i != -1; i = ne[i])
{
int b = e[i], c = w[i];
if(dist[b] > dist[a] + c){
dist[b] = dist[a] + c;
if(!st[b]){
q[++tt] = b;
st[b] = 1;
}
}
}
}
}
int main(){
memset(h, -1, sizeof h);
memset(dist, 0x3f, sizeof dist);
int n, m;
cin >> n >> m;
for(int i = 0; i < m; i++){
int a, b, w;
cin >> a >> b >> w;
add(a, b, w);
}
spfa();
if(dist[n] == 0x3f3f3f3f )
cout << "impossible";
else cout << dist[n];
return 0;
}
spfa求负环
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 2010, M = 10010;
int n, m;
int h[N], w[M], e[M], ne[M], idx;
int dist[N], cnt[N];
bool st[N];
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
bool spfa()
{
queue<int> q;
for (int i = 1; i <= n; i ++ )
{
st[i] = true;
q.push(i);
}
while (q.size())
{
int t = q.front();
q.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) return true;
if (!st[j])
{
q.push(j);
st[j] = true;
}
}
}
}
return false;
}
int main()
{
scanf("%d%d", &n, &m);
memset(h, -1, sizeof h);
while (m -- )
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
}
if (spfa()) puts("Yes");
else puts("No");
return 0;
}
Floyd
Floyd求最短路
#include <iostream>
using namespace std;
const int N = 210, M = 2e+10, INF = 1e9;
int n, m, k, x, y, z;
int d[N][N];
void floyd() {
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]);
}
int main() {
cin >> n >> m >> k;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
if(i == j) d[i][j] = 0;
else d[i][j] = INF;
while(m--) {
cin >> x >> y >> z;
d[x][y] = min(d[x][y], z);
}
floyd();
while(k--) {
cin >> x >> y;
if(d[x][y] > INF/2) puts("impossible");
else cout << d[x][y] << endl;
}
return 0;
}
Prim
Prim算法求最小生成树
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 510;
int g[N][N];
int dt[N];
int st[N];
int pre[N];
int n, m;
void prim()
{
memset(dt,0x3f, sizeof(dt));
int res= 0;
dt[1] = 0;
for(int i = 0; i < n; i++)
{
int t = -1;
for(int j = 1; j <= n; j++)
{
if(!st[j] && (t == -1 || dt[j] < dt[t]))
t = j;
}
if(dt[t] == 0x3f3f3f3f) {
cout << "impossible";
return;
}
st[t] = 1;
res += dt[t];
for(int i = 1; i <= n; i++)
{
if(dt[i] > g[t][i] && !st[i])
{
dt[i] = g[t][i];
pre[i] = t;
}
}
}
cout << res;
}
void getPath()
{
for(int i = n; i > 1; i--)
{
cout << i <<" " << pre[i] << " "<< endl;
}
}
int main()
{
memset(g, 0x3f, sizeof(g));
cin >> n >> m;
while(m --)
{
int a, b, w;
cin >> a >> b >> w;
g[a][b] = g[b][a] = min(g[a][b],w);
}
prim();
return 0;
}
Kruskal
算法求最小生成树
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
int p[N];
struct E{
int a;
int b;
int w;
bool operator < (const E& rhs){
return this->w < rhs.w;
}
}edg[N * 2];
int res = 0;
int n, m;
int cnt = 0;
int find(int a){
if(p[a] != a) p[a] = find(p[a]);
return p[a];
}
void klskr(){
for(int i = 1; i <= m; i++)
{
int pa = find(edg[i].a);
int pb = find(edg[i].b);
if(pa != pb){
res += edg[i].w;
p[pa] = pb;
cnt ++;
}
}
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i++) p[i] = i;
for(int i = 1; i <= m; i++){
int a, b , c;
cin >> a >> b >>c;
edg[i] = {a, b, c};
}
sort(edg + 1, edg + m + 1);
klskr();
if(cnt < n - 1) {
cout<< "impossible";
return 0;
}
cout << res;
return 0;
}
染色法判定二分图
染色法判定二分图
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010 * 2;
int e[N], ne[N], idx;
int h[N];
int color[N];
int n, m;
void add(int a, int b)
{
e[idx] = b, ne[idx]= h[a], h[a] = idx++;
}
bool dfs(int u, int c)
{
color[u] = c;
for(int i = h[u]; i!= -1; i = ne[i])
{
int b = e[i];
if(!color[b])
{
if(!dfs(b, 3 - c)) return false;
}
else if(color[b] && color[b] != 3 - c)
{
return false;
}
}
return true;
}
int main()
{
memset(h, -1, sizeof h);
cin >> n >> m;
for(int i = 1; i <= m; i++)
{
int a, b;
cin >> a >> b;
add(a, b), add(b, a);
}
for(int i = 1; i <= n; i++)
{
if(!color[i])
{
if(!dfs(i, 1))
{
cout << "No" << endl;
return 0;
}
}
}
cout << "Yes" << endl;
return 0;
}
匈牙利算法
二分图的最大匹配
#include<iostream>
#include <cstring>
#include<algorithm>
using namespace std;
int n1, n2, m;
int h[500], e[100010],ne[100010], idx = 0;
int st[510], match[510];
void add(int a, int b){
e[idx] = b, ne[idx] = h[a]; h[a] = idx++;
}
bool find(int x){
for(int i = h[x]; i != -1; i = ne[i]){
int b = e[i];
if(!st[b]){
st[b] = 1;
if(match[b] == 0 || find(match[b])){
match[b] = x;
return true;
}
}
}
return false;
}
int main(){
memset(h, -1, sizeof h);
cin >> n1 >> n2 >> m;
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, 0, sizeof st);
if(find(i)) res++;
}
cout << res;
return 0;
}