提交 5bbf825d 编写于 作者: qq_36480062's avatar qq_36480062

c

上级 3e54df58
import java.io.*;
import java.util.ArrayDeque;
import java.util.LinkedList;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.*;
import static java.lang.System.in;
......@@ -32,7 +29,8 @@ public class IO加速 {
}
public static void main(String[] args) throws IOException {
ff();
// fff();
sw();
// f();
// tokenizer = new StringTokenizer("123123 15412 4312412");
// System.out.println(tokenizer.nextToken());
......@@ -49,15 +47,82 @@ public class IO加速 {
// bw.flush();
}
static void fff() {
ArrayList<Integer> e = new ArrayList<Integer>();
Random r = new Random();
int te;
long s = System.nanoTime();
for (int i = 0; i < 1000000; i++) {
te = r.nextInt(100000);
e.add(te);
}
Collections.sort(e);
long t = System.nanoTime();
System.out.println((t - s) / 1e8);
s = System.nanoTime();
PriorityQueue<Integer> q = new PriorityQueue<Integer>(e);
while (!q.isEmpty()) q.poll();
t = System.nanoTime();
System.out.println((t - s) / 1e8);
}
static void sw() {
long s = System.nanoTime(); for (int i = 0; i < par.length; i++) {
par[i] = i;
}
for (int i = 0; i < par.length; i++) {
union(1, i);
}
long t = System.nanoTime();
System.out.println((t - s) / 1e8);
s = System.nanoTime(); for (int i = 0; i < par.length; i++) {
par[i] = i;
}
for (int i = 0; i < par.length; i++) {
unio(i, 0);
}
t = System.nanoTime();
System.out.println((t - s) / 1e8);
}
static void union(int x, int y) {
x = find(x);
y = find(y);
if (x != y) par[x] = y;
}
static void unio(int x, int y) {
x = fin(x);
y = fin(y);
if (x != y) par[x] = y;
}
static int find(int x) {
while (x != par[x]) {
par[x] = par[par[x]];
x = par[x];
}
return x;
}
static int fin(int x) {
if (x == par[x]) return x;
return par[x] = fin(par[x]);
}
static int[] par = new int[11000000];
static void ff() {
int a = 5, b = 5;
Random r = new Random();
int[] t = new int[3];
while (a > 0 && b > 0) {
for (int i = 0; i < 3; i++) {
int e=r.nextInt(13923);
int e = r.nextInt(13923);
System.out.println(e);
t[i] =e & 1;
t[i] = e & 1;
}
if (t[0] == t[1] && t[1] == t[2]) {
a++;
......
###Floyd
````
1. 多源多汇最短路 Floyd O(n^3)
2. 传递闭包
3. 最小环对于正权图,找边权和最小的环
和spfa不同的是,spfa判断的是负环
4. 找恰好经过k条边的最短路
(倍增)
Floyd做法
if i!=j d[i][j]=正无穷
if i==j d[i][j]=0
for k=1~n{
for i=1~n{
for j=1~n{
d[i,j]=min( d[i,j] , d[i,k]+d[k,j] )
}
}
}
dp分析:
状态表示: f[k,i,j] 所有从i点出发,最终走到j,
且中间只经过节点编号不超过k的所有路径
属性:路径长度的min
状态计算:状态划分:考虑last, 判断k这个点,
划分成2部分:所有路径包含节点k的路径,使得i走到k,k走到j路径最小
i~k取最小且k~j取最小:d[k-1][i][k]+d[k-1][k][j]
所有路径不包含节点k的路径:d[k-1][i][j]
直接去掉最高维,代码等价
d[i,j]=min( d[i,j] , d[i,k]+d[k,j] )
\ No newline at end of file
package graph.Floyd;
/**
* https://www.cnblogs.com/ctyakwf/p/12829458.html
*/
public class 牛的旅行 {
public static void main(String[] args) {
}
}
package graph.topoSort;
/**
* https://www.hzxueyan.com/archives/104/
*
*/
public class 奖金 {
public static void main(String[] args) {
}
}
package graph.topoSort;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Scanner;
/**
* 拓扑排序
* https://www.hzxueyan.com/archives/103/
* 入度为0的点加入队列,取出入度为0的点,并减去该点相邻的入度,
* 队列中实际上是存的所有入度为0的点,使用pq可以达到字典序
* 知道队列没有元素,该题一定有解,无解情况用vis判断,
*/
public class 家谱树 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
int s = 0;
for (int i = 1; i <= n; i++) {
while (true) {
s = sc.nextInt();
if (s == 0) break;
add(i, s);
in[s]++;
}
}
topo();
}
private static void topo() {
ArrayList<Integer> g = new ArrayList<Integer>();
ArrayDeque<Integer> q = new ArrayDeque<Integer>();
for (int i = 1; i <= n; i++) {
if (in[i] == 0) {
q.push(i);
g.add(i);
}
}
while (!q.isEmpty()) {
int t = q.poll();
for (int i = he[t]; i != 0; i = ne[i]) {
int j = e[i];
--in[j];
if (in[j] == 0) {
q.add(j);
g.add(j);
}
}
}
for (Integer w : g) {
System.out.println(w);
}
}
static int N = 110, M = N * N / 2, n, cnt = 1;
static int[] he = new int[N];
static int[] ne = new int[M];
static int[] e = new int[M];
static int[] in = new int[N];
// static int[] out = new int[N];
static void add(int a, int b) {
e[cnt] = b;
ne[cnt] = he[a];
he[a] = cnt++;
}
}
......@@ -8,6 +8,7 @@ import java.util.Scanner;
* https://blog.csdn.net/qq_43256272/article/details/103392889
* 使用spfa+dfs
* 复杂度 6*O(m)+5!
* 预处理出单源最短路
* 5!只有120不需要剪枝
*/
public class 新年好 {
......@@ -37,7 +38,7 @@ public class 新年好 {
* @param u 当前枚举到第几个
* @param start 当前起点
* @param dist 当前距离
* @return
* @return 花费
*/
static int dfs(int u, int start, int dist) {
if (u == 6) return dist;
......
......@@ -3,6 +3,8 @@ package graph.复合单源最短路;
import java.util.Scanner;
/**
* 从a到b,路径的长度定义为第k+1大值
* 二分:
*
*/
public class 通信线路 {
......
package graph.最小生成树拓展;
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.Scanner;
/**
* https://blog.csdn.net/qq_42279796/article/details/103211715
* 做最小生成树,把最大的几条边用卫星连接
* 抽象题目为:找一个最小的d值,是得所有权值大于d的边删去过后,整个图的连通块不超过k
* 具有单调性,随着d的增加,k单调减少
* 最终Kruskal本质上在求连通性
* 当前循环完第i条边,求出由前i条边所构成的所有连通块
*/
public class 北极通讯网络 {
public static void main(String[] args) {
for (int i = 0; i < par.length; i++) {
par[i] = i;
}
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
int k = sc.nextInt();
for (int i = 0; i < n; i++) {
list.add(new node(sc.nextInt(), sc.nextInt()));
}
PriorityQueue<node> q = new PriorityQueue<node>();
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
q.add(new node(i, j, getdist(list.get(i), list.get(j))));
}
}
int cnt = n;
double res = 0;
while (!q.isEmpty()) {
if (cnt <= k) break;
node p = q.poll();
int a = fin(p.x), b = fin(p.y);
double w = p.w;
if (a != b) {
par[a] = b;
cnt--;
res = w;
}
}
System.out.printf("%.2f", res);
}
private static double getdist(node a, node b) {
int dx = a.x - b.x;
int dy = a.y - b.y;
return Math.sqrt(dx * dx + dy * dy);
}
static ArrayList<node> list = new ArrayList<node>();
static class node implements Comparable<node> {
int x, y;
double w;
public node(int x, int y, double w) {
this.x = x;
this.y = y;
this.w = w;
}
public node(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public int compareTo(node node) {
return (int) (w * 1000 - node.w * 1000);
}
}
static int[] par = new int[250000];
static int n, m;
static int find(int x) {
while (x != par[x]) {
par[x] = par[par[x]];
x = par[x];
}
return x;
}
static int fin(int x) {
if (par[x] == x) return x;
return par[x] = fin(par[x]);
}
}
###次小生成树
````
定义:给定一个带权的图,把图的所有生成树按权值从小到大排序
第二小的称为次小生成树
则显然第一种定义,最小生成树和次小生成树的权值和相等
第二种定义:次小生成树严格大于最小生成树的权值和
次小生成树是权值和大于最小生成树的那个最小的那个生成树
两种写法相似
方法1:求最小生成树,再枚举删去最小生成树中的边求解
O(mlog m)+O(nm) 无法求严格次小生成树
方法2:先求最小生成树,依次枚举非树边,
然后将该边加入树,同时从树中去掉一条边,使得最终的图仍然是树,则一定可以求出次小生成树
package graph.最小生成树拓展;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
/**
* https://blog.csdn.net/qq_42279796/article/details/102526856
* 给定一个N个节点的树,
* 把这棵树扩充为完全图,并满足图的唯一最小生成树仍然是这棵树
* 连接两个集合的新边,
*/
public class 走廊泼水节 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
t = sc.nextInt();
ArrayList<node> q = new ArrayList<node>();
int[] size = new int[6100];
while (t-- != 0) {
q.clear();
n = sc.nextInt();
for (int i = 1; i < n; i++) {
q.add(new node(sc.nextInt(), sc.nextInt(), sc.nextInt()));
}
Collections.sort(q);
for (int i = 0; i < par.length; i++) {
par[i] = i;
size[i] = 1;
}
int res = 0;
for (int i = 0; i < n - 1; i++) {
node c = q.get(i);
int a = find(c.x), b = find(c.y);
if (a != b) {
res += (size[a] * size[b] - 1) * (c.w + 1);
size[b] += size[a];
par[a] = b;
}
}
System.out.println(res);
}
}
static int[] par = new int[6100];
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 find(int x) {
if (x == par[x]) return x;
return par[x] = find(par[x]);
}
static int t, n;
}
package graph.负环;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Scanner;
/**
* https://www.cnblogs.com/ctyakwf/p/12840842.html
* 2
* 3 3 1
* 1 2 2
* 1 3 4
* 2 3 1
* 3 1 3
* 3 2 1
* 1 2 3
* 2 3 4
* 3 1 8
*/
public class 虫洞 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
t = sc.nextInt();
int a, b, c;
while (t-- != 0) {
n = sc.nextInt();
m1 = sc.nextInt();
m2 = sc.nextInt();
idx = 1;
Arrays.fill(he, 0);
while (m1-- != 0) {
a = sc.nextInt();
b = sc.nextInt();
c = sc.nextInt();
add(a, b, c);
add(b, a, c);
}
while (m2-- != 0) {
a = sc.nextInt();
b = sc.nextInt();
c = sc.nextInt();
add(a, b, -c);
}
if (spfa()) System.out.println("YES");
else System.out.println("NO");
}
}
static ArrayDeque<Integer> q = new ArrayDeque<Integer>();
private static boolean spfa() {
Arrays.fill(dis, 0);
Arrays.fill(vis, false);
Arrays.fill(cnt, 0);
for (int i = 1; i <= n; i++) {
q.add(i);
vis[i] = true;
}
int p;
while (!q.isEmpty()) {
p = q.poll();
vis[p] = false;
for (int i = he[p]; i != 0; i = ne[i]) {
int j = e[i];
if (dis[j] > dis[p] + w[i]) {
dis[j] = dis[p] + w[i];
cnt[j] = cnt[p] + 1;
if (cnt[j] >= n) return true;
if (!vis[j]) {
q.add(j);
vis[j] = true;
}
}
}
}
return false;
}
static int t, n, m1, m2, idx = 1;
static int[] he = new int[510];
static int[] e = new int[5210];
static int[] ne = new int[5210];
static int[] w = new int[5210];
static int[] cnt = new int[510];
static int[] dis = new int[510];
static boolean[] vis = new boolean[510];
static void add(int a, int b, int c) {
e[idx] = b;
w[idx] = c;
ne[idx] = he[a];
he[a] = idx++;
}
}
###负环
````
存在一个环,其边权之和小于0
只要一个点可以走到负环上,可以在负环上走无穷次,
使得权值和为无穷小
01分数规划
求负环的常见方法基于spfa
1.统计每个点入队的次数,如果某个点入队n次,说明存在负环
类似于BellmanFord
最差O(n^2)
推荐2.统计当前每个点的最短路中所包含的边数,
如果某个点的最短路所包含的边数大于等于n,
则也说明存在环
O(n)推荐
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册