这题考察的是并查集,因为数据量过大所以这里我们使用快读快写,当数据的数量级为10^5时,用StreamTokenizer类差不多好像是要比Scanner快个300ms左右
import java.io.*;
public class Main{
static int N = 20010;
static int[] p = new int[N];
public static int find(int x){//并查集模板,寻找祖先,
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
public static void main(String[] args)throws IOException{
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
PrintWriter wt = new PrintWriter(new OutputStreamWriter(System.out));
String[] s1 = bf.readLine().split(" ");
int n = Integer.parseInt(s1[0]);
int m = Integer.parseInt(s1[1]);
for (int i = 1; i <= n; i ++) p[i] = i;
while (m -- > 0){
String[] s2 = bf.readLine().split(" "); //读入的时候用“ ”间隔
int a = Integer.parseInt(s2[0]);
int b = Integer.parseInt(s2[1]);
if (find(a) != find(b)) p[find(a)] = find(b);//让这两个节点成为亲戚
}
int q = Integer.parseInt(bf.readLine());
while (q -- > 0){
String[] s3 = bf.readLine().split(" ");
int a = Integer.parseInt(s3[0]);
int b = Integer.parseInt(s3[1]);
if (find(a) == find(b)) wt.println("Yes");
else wt.println("No");
}
wt.flush();
}
}
bfs寻找最短路,每一个点产生链接就是为一层,然后不断bfs,每一次入队刚好就可以遍历完一层,
import java.util.*;
public class Main {
static int N = 10010, M = 100010;
static int n, L, k, idx;
static int[] h = new int[N], e = new int[M], ne = new int[M];
static boolean[] st = new boolean[N]; //默认为false
public static void add(int a, int b) {
e[idx] = b; ne[idx] = h[a]; h[a] = idx++;
}
public static int bfs(int start) {
//每次访问都是独立的 需要重新初始化
Queue<Integer> q = new LinkedList<>();
Arrays.fill(st, false);
q.offer(start);
st[start] = true;
int res = 0;
for (int i = 0; i < L; i++) {
int sz = q.size(); //每一层的点数
while (sz -- > 0){
int t = q.poll();
for (int j = h[t]; j != -1; j = ne[j]) {
int x = e[j];
if (!st[x]){
q.offer(x);
st[x] = true;
res ++;
}
}
}
}
return res;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt(); L = sc.nextInt();
Arrays.fill(h, -1);
for (int i = 1; i <= n; i++) {
int cnt = sc.nextInt();
while (cnt -- > 0){
int x = sc.nextInt();
add(x, i);
}
}
k = sc.nextInt();
while (k -- > 0){
int x = sc.nextInt();
System.out.println(bfs(x));
}
}
}
用dfs在每个点都进行上下左右四个方向都走一次(当然要注意是否合法)
因为可以重复走, 所以遍历整个地图计算所有的可能性并存取到set集合当中,最后输出set的size就是答案数之和。
integer.parseInt()将string类型转换为int类型
import java.io.*;
import java.util.HashSet;
public class Main {
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
static int n, m, k;
static int[][] g = new int[6][6];
static int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};
static HashSet<Integer> set = new HashSet<>(); //用来存储遍历过的数
public static void dfs(int x, int y, int last, int index) {
if (index > k + 1) return; //当长度超过k + 1则返回
last = last * 10 + g[x][y]; //先先遍历的数在最高位
for (int i = 0; i < 4; i ++) {
int a = x + dx[i], b = y + dy[i];
if (a > 0 && a <= n && b > 0 && b <= m) dfs(a, b, last, index + 1);
String s = String.valueOf(last); //排除掉往回遍历的数,即实际长度不满足k + 1的数
if (index == k + 1 && s.length() == k + 1 && !set.contains(last)) set.add(last);
}
}
public static void main(String[] args) throws IOException {
String[] s1 = in.readLine().split(" ");
n = Integer.parseInt(s1[0]); m = Integer.parseInt(s1[1]); k = Integer.parseInt(s1[2]);
//初始化
for (int i = 1; i <= n; i ++) {
String[] s2 = in.readLine().split(" ");//将读取数据存到string数组之中
for (int j = 1; j <= m; j ++)
g[i][j] = Integer.parseInt(s2[j - 1]);
}
//遍历每个点
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j ++)
dfs(i, j, 0, 1);
out.println(set.size());
out.flush();
}
}
import java.io.*;
public class Main {
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
static int N = 1000010, n, mod = (int)1e9;
static int[][] f = new int[21][N]; //从前i个物品中选,价值恰好为j
static int[] w = new int[21]; //一共有0,2^0 ~ 2^19 二十种选法
public static void main(String[] args) throws Exception {
//初始化
for (int i = 1; i <= 20; i ++) w[i] = (int)Math.pow(2, i - 1);
n = Integer.parseInt(in.readLine());
for (int i = 0; i <= 20; i ++) f[i][0] = 1; //什么都不选是一种选法
for (int i = 1; i <= 20; i ++)
for (int j = 1; j <= n; j ++){
//不选2^i
f[i][j] = (f[i][j] + f[i - 1][j]) % mod;
if (j >= w[i])
//必选2^i,所以就不用考虑2^i,直接减去然后计算其他组合的情况
f[i][j] = (f[i][j] + f[i][j - w[i]]) % mod;
}
out.println(f[20][n]);
out.flush();
}
}