本专栏目录
蓝桥杯算法竞赛大纲数论相关(Java)
枚举相关(Java)
对象排序(Java)
字符串相关(Java)
排序相关算法(Java)
记忆化搜索(Java)
树论相关(Java)
图论相关(Java)
堆(Java)
贪心(Java)
文章目录
- 并查集_部落
- 并查集_社交集群
- 广度优先遍历解决联通图问题
- 深度优先遍历解决联通图问题
- 欧拉回路
- 拓扑排序_关键路径
- 拓扑排序_关键路径1
- 拓扑排序_最早完成时间
- 图最大着色数
- dijkstra基础模板
- dijkstra加dfs
- floyd基础模板
- prim基础模板
并查集_部落
package 图论;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class _并查集_部落 {
static int[] par = new int[10005];
static int max = -1;
static int[] vis;
static Set<Integer> set = new HashSet<>();
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
for (int i = 1; i < par.length; i++) {
par[i] = i;
}
int n = scan.nextInt();
for (int i = 0; i < n; i++) {
int m = scan.nextInt();
int pre = -1;
for (int j = 0; j < m; j++) {
int cur = scan.nextInt();
max = Math.max(cur, max); // 求最大编号
if (pre!=-1) merge(pre, cur);
pre = cur;
}
}
n = scan.nextInt();
System.out.print(max+" ");
vis = new int[max + 1];
for (int i = 1; i <= max; i++) {
set.add(findPar(i));
}
System.out.println(set.size());
for (int i = 0; i < n; i++) {
int a = scan.nextInt();
int b = scan.nextInt();
if (findPar(a)==findPar(b)){
System.out.println("Y");
}else {
System.out.println("N");
}
}
}
// 合并这两个节点
public static void merge(int a, int b){
a = findPar(a);
// b = findPar(b);
par[a] = b;
}
// 找父元素
public static int findPar(int ind){
while (par[ind]!=ind){
ind = par[ind];
}
return ind;
}
}
并查集_社交集群
package 图论;
import java.util.Arrays;
import java.util.Scanner;
// https://pintia.cn/problem-sets/994805046380707840/problems/994805053141925888
public class _并查集_社交集群 {
static int n;
static int[] par = new int[1005]; // 用于并查集
static int[] arr = new int[1005]; // 记录某人的一个爱好
static int[] count = new int[1005]; // 每种根集所有人数的数量
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
scan.nextLine();
for (int i = 1; i <= 1000; i++) {
par[i] = i;
}
for (int i = 1; i <= n; i++) {
String[] ss = scan.nextLine().replace(":","").split(" ");
int m = Integer.parseInt(ss[0]);
arr[i] = Integer.parseInt(ss[1]);
for (int j = 1; j <= m - 1; j++) {
int x = Integer.parseInt(ss[j]);
int y = Integer.parseInt(ss[j+1]);
merge(x,y);
}
}
for (int i = 1; i <= n; i++) {
int p = findP(arr[i]);
count[p]++;
}
Arrays.sort(count);
int c = 0;
for (int i = 1; i < 1005; i++) {
if (count[i]!=0) c++;
}
System.out.println(c);
System.out.print(count[count.length-1]);
for (int i = 2; i <= c; i++) {
System.out.print(" " + count[count.length-i]);
}
}
public static void merge(int x, int y){
x = findP(x);
par[x] = y;
}
public static int findP(int x){
while (x!=par[x]){
x = par[x];
}
return x;
}
}
广度优先遍历解决联通图问题
package 图论;
import java.util.ArrayList;
import java.util.List;
// 链接:https://leetcode-cn.com/problems/number-of-islands
public class _广度优先遍历解决联通图问题 {
public static void main(String[] args) {
char[][] grid = {
{'1', '1', '1', '1', '0'},
{'1', '1', '0', '1', '0'},
{'1', '1', '0', '0', '0'},
{'0', '0', '0', '0', '0'}
};
int sum = numIslands(grid);
System.out.println(sum);
}
public static int numIslands(char[][] grid) {
int sum = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (grid[i][j]=='1'){
bfs(grid, i, j);
sum++;
}
}
}
return sum;
}
public static void bfs(char[][] grid, int i, int j) {
grid[i][j]='0';
List<Node> ls = new ArrayList<>();
Node node = new Node(i, j);
ls.add(node);
while (!ls.isEmpty()){
node = ls.remove(0);
i = node.i;
j = node.j;
if (i-1>=0&&grid[i-1][j]=='1') {
grid[i-1][j] = '0'; // 提前标记,否则会标记很多次
ls.add(new Node(i-1,j));
}
if (i+1<=grid.length-1&&grid[i+1][j]=='1'){
grid[i+1][j] = '0';
ls.add(new Node(i+1, j));
}
if (j-1>=0&&grid[i][j-1]=='1'){
grid[i][j-1] = '0';
ls.add(new Node(i, j-1));
}
if (j+1<=grid[0].length-1&&grid[i][j+1]=='1'){
grid[i][j+1] = '0';
ls.add(new Node(i, j+1));
}
}
}
static class Node{
int i, j;
public Node(int i, int j) {
this.i = i;
this.j = j;
}
}
}
深度优先遍历解决联通图问题
package 图论;
// 链接:https://leetcode-cn.com/problems/number-of-islands
public class _深度优先遍历解决联通图问题 {
public static void main(String[] args) {
char[][] grid = {
{'1', '1', '1', '1', '0'},
{'1', '1', '0', '1', '0'},
{'1', '1', '0', '0', '0'},
{'0', '0', '0', '0', '0'}
};
int sum = numIslands(grid);
System.out.println(sum);
}
public static int numIslands(char[][] grid) {
int sum = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (grid[i][j]=='1'){
dfs(grid, i, j);
sum++;
}
}
}
return sum;
}
public static void dfs(char[][] grid, int i, int j) {
if (grid[i][j]=='0') return;
grid[i][j] = '0';
if (i-1>=0&&grid[i-1][j]=='1') dfs(grid,i-1,j);
if (i+1<=grid.length-1&&grid[i+1][j]=='1') dfs(grid,i+1, j);
if (j-1>=0&&grid[i][j-1]=='1') dfs(grid,i,j-1);
if (j+1<=grid[0].length-1&&grid[i][j+1]=='1') dfs(grid,i, j+1);
}
}
欧拉回路
package 图论;
/*
欧拉通路: 通过图中每条边且只通过一次,并且经过每一顶点的通路。
欧拉回路: 通过图中每条边且只通过一次,并且经过每一顶点的回路。
欧拉回路:图连通;图中所有节点度均为偶数
欧拉通路:图连通;图中只有0个或2个度为奇数的节点
*/
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class _欧拉回路 {
static int n,m;
static int [][] g;
static int[] deg;
static List<Integer> Q = new ArrayList<>();
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
m = scan.nextInt();
g = new int[n+1][n+1];
deg = new int[n+1];
for (int i = 0; i < m; i++) {
int a = scan.nextInt();
int b = scan.nextInt();
g[a][b]++;
g[b][a]++;
deg[a]++;
deg[b]++;
}
int num = 0;
int start = 1;
for (int i = 1; i <= n; i++) {
if ((deg[i]&1)==1){
num++;
start = i;
}
}
if (num==0 || num==2){
flery(start);
show();
}else {
System.out.println("No Euler path");
}
}
public static void flery(int start) {
dfs(start);
}
// 不到万不得已,不走桥
public static void dfs(int idx) {
for (int i = 1; i <= n; i++) {
if (g[idx][i]>0){
g[idx][i]--;
g[i][idx]--;
dfs(i);
}
}
Q.add(idx);
}
public static void show(){
while (!Q.isEmpty()){
System.out.print(Q.remove(0) + " ");
}
}
}
拓扑排序_关键路径
package 图论;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
// 拓扑排序后 dfs搜索最终等于max的,加入列表
public class _拓扑排序_关键路径 {
static int n,m;
static List<Node>[] tab;
static int[] in;
static int[] dis;
static List<Integer> Q = new ArrayList<>();
static List<Integer> start = new ArrayList<>();
static List<List<Integer>> paths = new ArrayList<>();
static List<Integer> temp = new ArrayList<>();
static int ans = 0;
static int max = -1;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
m = scan.nextInt();
in = new int[n];
dis = new int[n];
tab = new ArrayList[n];
for (int i = 0; i < n; i++) {
tab[i] = new ArrayList<>();
}
for (int i = 0; i < m; i++) {
int from = scan.nextInt();
int to = scan.nextInt();
int w = scan.nextInt();
Node node = new Node();
node.to = to;
node.w = w;
tab[from].add(node);
in[to]++;
}
for (int i = 0; i < n; i++) {
if (in[i]==0){
Q.add(i);
start.add(i);
}
}
fn();
if (ans != n){
System.out.println("Impossible");
return;
}
// 将用时最长的最后一个工程加入List中
max = -1;
for (int i = 0; i < n; i++) {
max = Math.max(max, dis[i]);
}
System.out.println(max);
for (int i = 0; i < start.size(); i++) {
dfs(start.get(i), 0);
}
for (List<Integer> ls: paths) {
System.out.print(ls.get(0));
for (int i = 1; i < ls.size(); i++) {
System.out.print("-->" + ls.get(i));
}
System.out.println();
}
}
private static void dfs(int v, int sumw) {
temp.add(v);
List<Node> ls = tab[v];
if (sumw == max){
List<Integer> ll = new ArrayList<>();
ll.addAll(temp);
paths.add(ll);
temp.remove(temp.size()-1);
return;
}
for (int i = 0; i < ls.size(); i++) {
Node node = ls.get(i);
int t = node.to;
int w = node.w;
dfs(t, sumw + w);
}
temp.remove(temp.size()-1);
}
public static void fn() {
int t;
while (!Q.isEmpty()){
t = Q.remove(0);
ans++;
List<Node> ls = tab[t];
for (int i = 0; i < ls.size(); i++) {
Node node = ls.get(i);
int w = node.w;
int id = node.to;
in[id]--;
if (in[id]==0){
Q.add(id);
}
if (dis[t]+w > dis[id]){
dis[id] = dis[t]+w;
}
}
}
}
static class Node{
int w;
int to;
}
}
拓扑排序_关键路径1
package 图论;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class _拓扑排序_关键路径1 {
static int n,m;
static List<Node>[] tab;
static List<Node>[] revtab;
static int[] in;
static int[] revin;
static int[] dis;
static int[] revdis;
static List<Integer> Q = new ArrayList<>();
static List<Integer> end = new ArrayList<>();
static List<Integer> start = new ArrayList<>();
static List<Integer> revQ = new ArrayList<>();
static List<List<Integer>> paths = new ArrayList<>();
static List<Integer> temp = new ArrayList<>();
static int ans = 0;
static int inf = 9999999;
static int max = -1;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
m = scan.nextInt();
in = new int[n];
revin = new int[n];
dis = new int[n];
revdis = new int[n];
tab = new ArrayList[n];
revtab = new ArrayList[n];
for (int i = 0; i < n; i++) {
tab[i] = new ArrayList<>();
revtab[i] = new ArrayList<>();
revdis[i] = inf;
}
for (int i = 0; i < m; i++) {
int from = scan.nextInt();
int to = scan.nextInt();
int w = scan.nextInt();
Node node = new Node();
node.to = to;
node.w = w;
tab[from].add(node);
in[to]++;
node = new Node();
node.to = from;
node.w = w;
revtab[to].add(node);
revin[from]++;
}
for (int i = 0; i < n; i++) {
if (in[i]==0){
Q.add(i);
start.add(i);
}
}
fn();
if (ans != n){
System.out.println("Impossible");
return;
}
// 将用时最长的最后一个工程加入List中
max = -1;
for (int i = 0; i < n; i++) {
if (dis[i]>max){
max = dis[i];
end.clear();
end.add(i);
}else if(dis[i]==max){
end.add(i);
}
}
System.out.println(max);
for (int i = 0; i < end.size(); i++) {
int v = end.get(i);
revQ.add(v);
revdis[v] = dis[v];
}
revfn();
for (int i = 0; i < start.size(); i++) {
dfs(start.get(i), 0);
}
for (List<Integer> ls: paths) {
System.out.print(ls.get(0));
for (int i = 1; i < ls.size(); i++) {
System.out.print("-->" + ls.get(i));
}
System.out.println();
}
}
private static void dfs(int v, int sumw) {
if (dis[v]!=revdis[v]){
return;
}
temp.add(v);
List<Node> ls = tab[v];
if (sumw == max){
List<Integer> ll = new ArrayList<>();
ll.addAll(temp);
paths.add(ll);
temp.remove(temp.size()-1);
return;
}
for (int i = 0; i < ls.size(); i++) {
Node node = ls.get(i);
int t = node.to;
int w = node.w;
dfs(t, sumw + w);
}
temp.remove(temp.size()-1);
}
public static void revfn() {
int t;
while (!revQ.isEmpty()){
t = revQ.remove(0);
List<Node> ls = revtab[t];
for (int i = 0; i < ls.size(); i++) {
Node node = ls.get(i);
int v = node.to;
int w = node.w;
revin[v]--;
if (revin[v]==0){
revQ.add(v);
}
revdis[v] = Math.min(revdis[v], revdis[t] - w);
}
}
}
public static void fn() {
int t;
while (!Q.isEmpty()){
t = Q.remove(0);
ans++;
List<Node> ls = tab[t];
for (int i = 0; i < ls.size(); i++) {
Node node = ls.get(i);
int w = node.w;
int id = node.to;
in[id]--;
if (in[id]==0){
Q.add(id);
}
if (dis[t]+w > dis[id]){
dis[id] = dis[t]+w;
}
}
}
}
static class Node{
int w;
int to;
}
}
拓扑排序_最早完成时间
package 图论;
/
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class _拓扑排序_最早完成时间 {
static int n,m;
static List<Node>[] tab;
static int[] in;
static int[] dis;
static List<Integer> Q = new ArrayList<>();
static int ans = 0;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
m = scan.nextInt();
in = new int[n];
dis = new int[n];
tab = new ArrayList[n];
for (int i = 0; i < n; i++) {
tab[i] = new ArrayList<>();
}
for (int i = 0; i < m; i++) {
int from = scan.nextInt();
int to = scan.nextInt();
int w = scan.nextInt();
Node node = new Node();
node.to = to;
node.w = w;
tab[from].add(node);
in[to]++;
}
for (int i = 0; i < n; i++) {
if (in[i]==0){
Q.add(i);
}
}
fn();
if (ans != n){
System.out.println("Impossible");
return;
}
int max = -1;
for (int i = 0; i < n; i++) {
max = Math.max(max, dis[i]);
}
System.out.println(max);
}
public static void fn() {
while (!Q.isEmpty()){
int t = Q.remove(0);
ans++;
List<Node> ls = tab[t];
for (int i = 0; i < ls.size(); i++) {
Node node = ls.get(i);
int w = node.w;
int id = node.to;
in[id]--;
if (in[id]==0){
Q.add(id);
}
if (dis[t]+w > dis[id]){
dis[id] = dis[t]+w;
}
}
}
}
static class Node{
int w;
int to;
}
}
图最大着色数
package 图论;
import java.util.Scanner;
// https://www.lanqiao.cn/problems/109/learning/
public class _图最大着色数 {
static int n;
static int m;
static int maxC; // 最大颜色数
static int[][] tab;
static int[] color;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
m = scan.nextInt();
tab = new int[n+1][n+1];
color = new int[n+1];
for (int i = 0; i < m; i++) {
int a = scan.nextInt();
int b = scan.nextInt();
tab[a][b] = 1;
tab[b][a] = 1;
}
tryNum();
}
public static boolean check(int cur){
for (int i = 1; i <= n; i++) {
if (cur == i) continue;
if (tab[cur][i]==1&&color[i]==color[cur]){
return false;
}
}
return true;
}
public static boolean dfs(int cur, int col) {
if (col>maxC) return false;
if (cur>n) return true;
for (int i = 1; i <= col; i++) {
color[cur] = i;
if (check(cur)&&dfs(cur+1,col)){
// color[cur] = 0;
return true;
}
// color[cur] = 0;
}
color[cur] = col + 1;
if (dfs(cur+1, col + 1) && check(cur)){
return true;
}
return false;
}
public static void tryNum(){
for (int i = 1; i <= 100; i++) {
maxC = i;
if (dfs(1, 1)){
System.out.println(i);
break;
}
}
}
}
dijkstra基础模板
package 图论;
import java.util.Scanner;
public class _dijkstra基础模板 {
static int n, m;
static int[][] tab;
static int[] vis;
static int[] pre;
static int[] dis;
static int inf = 99999999;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
m = scan.nextInt();
tab = new int[n+1][n+1];
vis = new int[n+1];
pre = new int[n+1];
dis = new int[n+1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n ; j++) {
if (i==j){
tab[i][j] = 0;
}else {
tab[i][j] = inf;
}
}
}
for (int i = 0; i < m; i++) {
int a = scan.nextInt();
int b = scan.nextInt();
int w = scan.nextInt();
tab[a][b] = w;
tab[b][a] = w;
}
int v = scan.nextInt();
int s = scan.nextInt();
dijkstra(v);
System.out.println(dis[s]);
}
public static void dijkstra(int v) {
vis[v] = 1;
for (int i = 1; i <= n; i++) {
dis[i] = tab[v][i];
pre[i] = v;
}
for (int i = 0; i < n-1; i++) {
int ind = -1;
int min = inf;
for (int j = 1; j <= n; j++) {
if (vis[j]==0 && dis[j] < min){
min = dis[j];
ind = j;
}
}
vis[ind] = 1;
for (int j = 1; j <= n; j++) {
if (vis[j]==0 && dis[ind] + tab[ind][j] < dis[j]){
dis[j] = dis[ind] + tab[ind][j];
pre[j] = ind;
}
}
}
}
}
dijkstra加dfs
package 图论;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class _dijkstra加dfs {
static int n,m,s,d;
static int maxnums = -1;
static int roads = 0;
static int inf = 9999999;
static int[] pnum;
static int[] vis;
static int[] dis;
static int[][] tab;
static List<Integer>[] pre;
static List<Integer> path = new ArrayList<>();
static List<Integer> temp = new ArrayList<>();
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
m = scan.nextInt();
s = scan.nextInt();
d = scan.nextInt();
pnum = new int[n];
vis = new int[n];
dis = new int[n];
tab = new int[n][n];
pre = new ArrayList[n];
for (int i = 0; i < n; i++) {
pnum[i] = scan.nextInt();
pre[i] = new ArrayList<>();
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
tab[i][j] = inf;
}
}
for (int i = 0; i < m; i++) {
int a = scan.nextInt();
int b = scan.nextInt();
int w = scan.nextInt();
tab[a][b] = w;
tab[b][a] = w;
}
dijkstra(s);
dfs(d);
System.out.println(roads + " " + maxnums);
for (int i = path.size()-1; i > 0; i--) {
System.out.print(path.get(i) + " ");
}
System.out.println(path.get(0));
}
private static void dfs(int v) {
temp.add(v);
if (v==s){
roads++;
int nums = 0;
for (int i = 0; i < temp.size(); i++) {
nums += pnum[temp.get(i)];
}
if (maxnums < nums){
path.clear();
path.addAll(temp);
maxnums = nums;
}
temp.remove(temp.size()-1);
return;
}
for (int i = 0; i < pre[v].size(); i++) {
dfs(pre[v].get(i));
}
temp.remove(temp.size()-1);
}
private static void dijkstra(int s) {
vis[s] = 1;
for (int i = 0; i < n; i++) {
dis[i] = tab[s][i];
pre[i].add(s);
}
for (int i = 0; i < n - 1; i++) {
int ind = -1;
int min = inf;
for (int j = 0; j < n; j++) {
if (vis[j]==0&&dis[j]<min){
min = dis[j];
ind = j;
}
}
vis[ind] = 1;
for (int j = 0; j < n; j++) {
if (vis[j]==0 && dis[ind] + tab[ind][j] < dis[j]){
dis[j] = dis[ind] + tab[ind][j];
pre[j].clear();
pre[j].add(ind);
}else if (vis[j]==0 && dis[ind] + tab[ind][j] == dis[j]){
pre[j].add(ind);
}
}
}
}
}
floyd基础模板
package 图论;
import java.util.Scanner;
public class _floyd基础模板 {
static int n, m;
static int[][] tab;
static int[][] pre;
static int inf = 9999999;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
m = scan.nextInt();
tab = new int[n][n];
pre = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
tab[i][j] = inf;
pre[i][j] = i;
}
}
for (int i = 0; i < m; i++) {
int a = scan.nextInt();
int b = scan.nextInt();
int w = scan.nextInt();
tab[a][b] = w;
tab[b][a] = w;
}
floyd();
int u = scan.nextInt();
int v = scan.nextInt();
System.out.println(tab[u][v]);
int x = u;
System.out.printf("-->%d", v);
while (u!=pre[u][x]){
x = pre[u][x];
System.out.printf("-->%d", x);
}
System.out.printf("-->%d", u);
}
public static void floyd() {
for (int k = 0; k < n; k++) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (tab[i][k]+tab[k][j] < tab[i][j]){
tab[i][j] = tab[i][k]+tab[k][j];
pre[i][j] = k;
}
}
}
}
}
}
prim基础模板
package 图论;
import java.util.Scanner;
public class _prim基础模板 {
static int n, m;
static int[][] tab;
static int[] vis;
static int[] dis;
static int inf = 9999999;
static long sum = 0;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
m = scan.nextInt();
tab = new int[n][n];
vis = new int[n];
dis = new int[n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
tab[i][j] = inf;
}
}
for (int i = 0; i < m; i++) {
int a = scan.nextInt();
int b = scan.nextInt();
int w = scan.nextInt();
tab[a][b] = w;
tab[b][a] = w;
}
prim(0);
System.out.println(sum);
}
private static void prim(int v) {
vis[v] = 1;
// dis数组记录的是所有在树上的节点到未在树上的节点j之间最短的边
for (int i = 0; i < n; i++) {
dis[i] = tab[v][i];
}
for (int i = 0; i < n - 1; i++) {
int ind = -1;
int min = inf;
// 找未标记的点到已标记的点中边最小的
for (int j = 0; j < n; j++) {
if (vis[j]==0 && dis[j] < min) {
min = dis[j];
ind = j;
}
}
sum += min;
vis[ind] = 1;
// 更新所有在树上的节点到未在树上的节点j之间最短的边
for (int j = 0; j < n; j++) {
if (vis[j]==0&&dis[j] > tab[ind][j]){
dis[j] = tab[ind][j];
}
}
System.out.printf("%d ", ind);
}
}
}