提交 3e54df58 编写于 作者: qq_36480062's avatar qq_36480062

c

上级 561c2006
package String;
/**
*
* Tire
*/
public class 前缀统计 {
public static void main(String[] args) {
......
......@@ -25,6 +25,11 @@ public class 树重心找节点 {
}
dfs(1);
System.out.println(Arrays.toString(maxpart));
for (int i = 1; i <= n; i++) {
if (maxpart[i] == ans) {
System.out.println(i);
}
}
}
private static void dfs(int u) {
......@@ -37,7 +42,7 @@ public class 树重心找节点 {
size[u] += size[j];
//u节点加上所有子节点
maxpart[u] = Math.max(maxpart[u], size[j]);
//取u的最大部分
//取u的最大部分,必须要有
}
maxpart[u] = Math.max(maxpart[u], n - size[u]);
//算出以u为根的子树,u的父节点所在联通分量的节点数目
......
package graph.单源最短路;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.Scanner;
public class 紧急情况 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
s = sc.nextInt();
t = sc.nextInt();
for (int i = 0; i < n; i++) {
g[i] = sc.nextInt();
}
int a, b, c;
for (int i = 0; i < m; i++) {
a = sc.nextInt();
b = sc.nextInt();
c = sc.nextInt();
add(a, b, c);
add(b, a, c);
}
for (int i = he[0]; i != 0; i = ne[i]) {
System.out.println(e[i]);
}
dijkstra(s);
}
static void dijkstra(int s) {
Arrays.fill(dis, Integer.MAX_VALUE / 2);
PriorityQueue<node> q = new PriorityQueue<node>();
dis[s] = 0;
q.add(new node(s, 0));
while (!q.isEmpty()) {
node p = q.poll();
int x = p.to;
if (vis[x]) continue;
vis[x] = true;
for (int i = he[x]; i != 0; i = ne[i]) {
int j = e[i];
if (dis[j] > dis[x] + w[i]) {
dis[j] = dis[x] + w[i];
q.add(new node(j, dis[j]));
pre[j] = x;
}
}
}
int cur = t;
int ans = 0;
while (cur != 0) {
ans += g[cur];
cur = pre[cur];
}
System.out.println(Arrays.toString(dis));
System.out.println(dis[t]);
System.out.println(ans);
}
static class node implements Comparable<node> {
int to, dis;
public node(int to, int dis) {
this.to = to;
this.dis = dis;
}
@Override
public int compareTo(node node) {
return dis - node.dis;
}
}
static boolean[] vis = new boolean[510];
static int[] dis = new int[510];
static int[] pre = new int[510];
static int[] g = new int[510];
static int n, m, s, t, cnt = 1;
static int[] he = new int[510];
static int[] ne = new int[1210];
static int[] e = new int[1210];
static int[] w = new int[1210];
static void add(int a, int b, int c) {
e[cnt] = b;
w[cnt] = c;
ne[cnt] = he[a];
he[a] = cnt++;
}
}
package graph.最小生成树;
import java.util.PriorityQueue;
import java.util.Scanner;
/**
* https://blog.csdn.net/weixin_43872728/article/details/105852223
* 求最小生成森林
* 求每一个联通块的,最小生成树
* 使用Kruskal算法最好写,即使算法没有进行完,那么算法也是正确的
*/
public class 局域网 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
for (int i = 0; i < par.length; i++) {
par[i] = i;
}
PriorityQueue<node> q = new PriorityQueue<node>();
for (int i = 0; i < m; i++) {
q.add(new node(sc.nextInt(), sc.nextInt(), sc.nextInt()));
}
int res = 0;
while (!q.isEmpty()) {
node p = q.poll();
if (!is(p.x, p.y)) union(p.x, p.y);
else res += p.w;
}
System.out.println(res);
}
static boolean is(int x, int y) {
return find(x) == find(y);
}
static int find(int x) {
while (x != par[x]) {
par[x] = par[par[x]];
x = par[x];
}
return x;
}
static void union(int x, int y) {
int xRoot = find(x);
int yRoot = find(y);
if (xRoot != yRoot) par[xRoot] = yRoot;
}
static class node implements Comparable<node> {
int x, y, w;
public node(int x, int y, int w) {
this.x = x;
this.y = y;
this.w = w;
}
@Override
public int compareTo(node node) {
return w - node.w;
}
}
static int[] par = new int[110];
static int n, m;
}
````
最小生成树:边权之和最小
````
##Prim
````
朴素Prim O(n^2) 使用邻接矩阵存图
堆优化 Prim 被Kruskal完爆
````
###Kruskal 稀疏图
````
O(m log n)
直接存边
并查集
n个点的完全图有n(n-1)条边
package graph.最小生成树;
import java.util.Arrays;
import java.util.Scanner;
/**
* https://www.hzxueyan.com/archives/94/
* 最小生成树模板
* 农夫约翰被选为他们镇的镇长!
* 他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场。
* 约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场。
* 约翰的农场的编号是 1,其他农场的编号是 2 ∼ n。
* 为了使花费最少,他希望用于连接所有的农场的光纤总长度尽可能短。
* 你将得到一份各农场之间连接距离的列表,你必须找出能连接所有农场并使所用光纤最短的方案。
* 输入
* 第一行包含一个整数 n,表示农场个数。
* 接下来 n 行,每行包含 n 个整数,输入一个对角线上全是 0 的对称矩阵。
* 其中第 x + 1 行 y 列的整数表示连接农场 x 和农场 y 所需要的光纤长度。
* 输出
* 输出一个整数,表示所需的最小光纤长度。
* 数据范围
* 3≤n≤100
* 每两个农场间的距离均是非负整数且不超过 100000100000。
* 输入样例
* 4
* 0 4 9 21
* 4 0 8 17
* 9 8 0 16
* 21 17 16 0
* 输出样例
* 28
*/
public class 最短网络 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
g[i][j] = sc.nextInt();
}
}
System.out.println(prim());
}
static int prim() {
int res = 0;
Arrays.fill(dis, Integer.MAX_VALUE / 2);
dis[1] = 0;
for (int i = 0; i < n; i++) {
int t = -1;
for (int j = 1; j <= n; j++) {
if (!vis[j] && (t == -1 || dis[t] > dis[j])) {
t = j;
}
}
if (i != 0 && dis[t] == Integer.MAX_VALUE / 2) return Integer.MAX_VALUE / 2;
//进行了一轮还是无穷,说明不联通,不存在最小生成树
res += dis[t];
vis[t] = true;
for (int j = 1; j <= n; j++) {
dis[j] = Math.min(dis[j], g[t][j]);
}
}
return res;
}
static int[][] g = new int[110][110];
static int n;
static int[] dis = new int[110];
static boolean[] vis = new boolean[110];
}
package graph.最小生成树;
import java.util.PriorityQueue;
import java.util.Scanner;
/**
* https://www.acwing.com/activity/content/code/content/308366/
* 求出无向图最小生成树中,最长边权的最小值
* 最小生成树必然是n-1条边,
*/
public class 繁忙的都市 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
for (int i = 0; i < par.length; i++) {
par[i] = i;
}
n = sc.nextInt();
m = sc.nextInt();
PriorityQueue<node> q = new PriorityQueue<node>();
for (int i = 0; i < m; i++) {
q.add(new node(sc.nextInt(), sc.nextInt(), sc.nextInt()));
}
int ans = 0;
while (!q.isEmpty()) {
node p = q.poll();
if (!is(p.x, p.y)) {
union(p.x, p.y);
ans = p.w;
}
}
System.out.println(n-1+" "+ans);
}
static void union(int x, int y) {
int xroot = find(x);
int yroot = find(y);
if (yroot != xroot) par[xroot] = yroot;
}
static boolean is(int x, int y) {
return find(x) == find(y);
}
static int find(int x) {
while (x != par[x]) {
par[x] = par[par[x]];
x = par[x];
}
return x;
}
static int[] par = new int[1010];
static class node implements Comparable<node> {
int x, y, w;
public node(int x, int y, int w) {
this.x = x;
this.y = y;
this.w = w;
}
@Override
public int compareTo(node node) {
return w - node.w;
}
}
static int n, m;
}
package graph.最小生成树;
import java.util.PriorityQueue;
import java.util.Scanner;
/**
* https://www.acwing.com/activity/content/code/content/308367/
* 有一些必选边,一些可选边组成最小生成树
* 也是用Kruskal算法,
* 精髓在于Kruskal进行到一半,也是正确的
*/
public class 联络员 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
for (int i = 0; i <= n; i++) {
par[i] = i;
}
PriorityQueue<node> q = new PriorityQueue<node>();
int res = 0;
int t, a, b, c;
for (int i = 0; i < m; i++) {
t = sc.nextInt();
a = sc.nextInt();
b = sc.nextInt();
c = sc.nextInt();
if (t == 1) {
res += c;
union(a, b);
} else {
q.add(new node(a, b, c));
}
}
while (!q.isEmpty()) {
node p = q.poll();
if (!is(p.x, p.y)) {
union(p.x, p.y);
res += p.w;
}
}
System.out.println(res);
}
static int[] par = new int[1100];
static int n, m;
static void union(int x, int y) {
int xroot = find(x);
int yroot = find(y);
if (yroot != xroot) par[xroot] = yroot;
}
static int find(int x) {
while (x != par[x]) {
par[x] = par[par[x]];
x = par[x];
}
return x;
}
static boolean is(int x, int y) {
return find(x) == find(y);
}
static class node implements Comparable<node> {
int x, y, w;
public node(int x, int y, int w) {
this.x = x;
this.y = y;
this.w = w;
}
@Override
public int compareTo(node node) {
return w - node.w;
}
}
}
package graph.最小生成树;
import java.util.Scanner;
/**
* https://blog.csdn.net/qq_42279796/article/details/103091446
* 依然Kruskal
* 先选一些,再用Kruskal
* 把二维坐标转化为一维坐标
*/
public class 连接格点 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
for (int i = 0; i <= n * m; i++) {
par[i] = i;
}
int a, b, c, d;
for (int i = 1, t = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
g[i][j] = t++;
}
}
while (sc.hasNext()) {
a = sc.nextInt();
b = sc.nextInt();
c = sc.nextInt();
d = sc.nextInt();
union(g[a][b], g[c][d]);
}
int res = 0;
int[] dx = {-1, 0, 1, 0};
int[] dy = {0, 1, 0, -1};
int[] dw = {1, 2, 1, 2};
//枚举横向边
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
for (int u = 0; u < 4; u++) {
a = dx[u] + i;
b = dy[u] + j;
if (a < 1 || a > n || b < 1 || b > m || u % 2 == 1) continue;
if (is(g[a][b], g[i][j])) {
res++;
union(g[a][b], g[i][j]);
}
}
}
}
//枚举纵向边
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
for (int u = 0; u < 4; u++) {
a = dx[u] + i;
b = dy[u] + j;
int w = dw[u];
if (a < 1 || a > n || b < 1 || b > m || u % 2 == 0) continue;
if (is(g[a][b], g[i][j])) {
res += 2;
union(g[a][b], g[i][j]);
}
}
}
}
System.out.println(res);
}
private static void getedge() {
int[] dx = {-1, 0, 1, 0};
int[] dy = {0, 1, 0, -1};
int[] dw = {1, 2, 1, 2};
for (int z = 0; z < 2; z++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
for (int u = 0; u < 4; u++) {
if (u % 2 == z) {
int x = i + dx[u], y = j + dy[u], w = dw[u];
if (x != 0 && x <= n && y != 0 && y <= m) {
int a = g[i][j], b = g[x][y];
if (a < b) edge[k++] = new node(a, b, w);
}
}
}
}
}
}
}
static class node {
int x, y, w;
public node(int x, int y, int w) {
this.x = x;
this.y = y;
this.w = w;
}
}
static int N = 1000;
static node[] edge = new node[N];
static int n, m, k;
static int[][] g = new int[N][N];
static int[] par = new int[1000000];
static boolean is(int x, int y) {
return find(x) == find(y);
}
static int find(int x) {
while (x != par[x]) {
par[x] = par[par[x]];
x = par[x];
}
return x;
}
static void union(int x, int y) {
int xRoot = find(x);
int yRoot = find(y);
if (xRoot != yRoot) par[xRoot] = yRoot;
}
}
package graph.最小生成树拓展;
/**
* https://blog.csdn.net/qq_42279796/article/details/103211715
* 做最小生成树,把最大的几条边用卫星连接
*/
public class 北极通讯网络 {
public static void main(String[] args) {
}
}
package graph.最小生成树拓展;
import java.util.Arrays;
import java.util.Scanner;
/**
* https://blog.csdn.net/qq_42279796/article/details/103211427
* 本来不是最小生成树问题
* 把在该节点新建一条边,看做向虚拟源点(0号点)连一条边
* 虚拟源点,是个非常重要的技巧,这样就变成了最小生成树问题
*
*/
public class 新的开始 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i = 1; i <= n; i++) {
g[0][i] = g[i][0] = sc.nextInt();
}//把0号点看做超级源点
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
g[i][j] = sc.nextInt();
}
}
System.out.println(prim());
}
static int[][] g = new int[310][310];
static int n;
static int[] dis = new int[310];
static boolean[] vis = new boolean[310];
static int prim() {
Arrays.fill(dis, Integer.MAX_VALUE / 2);
dis[0] = 0;
int ans = 0;
//n+1个点,找n条边
for (int i = 0; i <= n; i++) {
int s = -1;
for (int j = 0; j <= n; j++) {
if (!vis[j] && (s == -1 || dis[j] < dis[s]))
s = j;
}
vis[s] = true;
ans += dis[s];
for (int j = 0; j <= n; j++) {
dis[j] = Math.min(dis[j], g[s][j]);
}
}
return ans;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册