JAVA蓝桥国赛备战

2019.5.16

二分:POJ - 3258

有一堆牛要过河,河的长度是l,河中间有n个石头,牛只能踩着石头过河,问去掉m个石头后(去掉这m个石头的方式是随机的)的每种情况牛能走的石头间距最小值中,最大的那一个是多少

输入:25 5 2//河的长度,一共有几块石头,去掉m块

          2 14 11 21 17//这n块石头的位置

输出:4

思路:二分距离 check函数注意写法

 1 import java.util.Arrays;
 2 import java.util.Scanner;
 3 
 4 public class Main {
 5     static int n,m;
 6     static int len;
 7     static int [] b = new int [50010];
 8     static boolean check(int x) {
 9         int cnt = 0;
10         int pos = 0;
11         
12         for(int i=1;i<=n+1;i++) {
13             
14             if(b[i]-b[pos]<x) {
15                 
16                 cnt++;
17                 if(cnt>m)
18                     return false;
19             }
20             else
21                 pos = i;
22         }
23         return true;
24     }
25     public static void main(String[] args) {
26         Scanner cin = new Scanner(System.in);
27         len = cin.nextInt();
28         n = cin.nextInt();
29         m = cin.nextInt();
30         for(int i=1;i<=n;i++)
31             b[i] = cin.nextInt();
32         b[0] = 0;
33         b[n+1] = len;
34         Arrays.sort(b, 0, n+2);
35         
36         int l = 0, r = len;
37         int ans = 0;
38         while(l<=r) {
39             int mid = (l+r)/2;
40             if(check(mid)) {
41                 l = mid + 1;
42                 ans = mid;
43             }
44             else
45                 r = mid - 1;
46         }
47         System.out.println(ans);
48     }
49 }

 2019.5.17

  昨天肚子疼,没怎么干活 今天补上。

dijkstra 用我自己写的怎么写怎么RE,改成了某大神的:

5个顶点1~5,5条双向边。求从1到n的最短路
5 5 1 2 20 2 3 30 3 4 20 4 5 20 1 5 100
输出 90
 1 import java.util.Arrays;
 2 import java.util.PriorityQueue;
 3 import java.util.Scanner;
 4 
 5 class node implements Comparable<node>{
 6     int to;
 7     int w;
 8     int next;
 9     public node(int to,int w,int next) {
10         this.to= to;
11         this.w = w;
12         this.next = next;
13         // TODO Auto-generated constructor stub
14     }
15     @Override
16     public int compareTo(node x) {
17         // TODO Auto-generated method stub
18         return this.w-x.w;
19     }
20 }
21 public class Main {
22     static final int inf = 0x3f3f3f3f;
23     static int m,n,cnt;
24     static node [] e;
25     static int [] vis,dis,head;
26     static PriorityQueue<node> q = new PriorityQueue<node>();
27     static void init() {
28         e = new node[2*m];
29         head = new int [n+10];
30         vis = new int [n+10];
31         dis = new int [n+10];
32         Arrays.fill(dis, inf);
33         Arrays.fill(head, -1);
34         cnt = 0;
35     }
36     static void add(int x,int y,int w) {
37         e[cnt] = new node(y, w, head[x]);
38         head[x] = cnt++;
39     }
40     static void dijkstra(int st) {
41         dis[st] = 0;
42         q.offer(new node(st, 0, 0));
43         while(!q.isEmpty()) {
44             int pos = q.poll().to;
45             if(vis[pos]==1)
46                 continue;
47             vis[pos] = 1;
48             for(int i=head[pos];i!=-1;i=e[i].next) {
49                 int to = e[i].to;
50                 if(dis[to]>dis[pos]+e[i].w) {
51                     dis[to] = dis[pos] + e[i].w;
52                     q.offer(new node(to, dis[to], 0));
53                 }
54             }
55         }
56         System.out.println(dis[n]);
57     }
58     public static void main(String[] args) {
59         Scanner cin = new Scanner(System.in);
60         m = cin.nextInt();
61         n = cin.nextInt();
62         init();
63         int a,b,c;
64         for(int i=0;i<m;i++) {
65             a = cin.nextInt();
66             b = cin.nextInt();
67             c = cin.nextInt();
68             add(a, b, c);
69             add(b, a, c);
70         }
71         dijkstra(1);
72     }
73 }

 5.19

tarjan强连通:

题目描述

在幻想乡,上白泽慧音是以知识渊博闻名的老师。春雪异变导致人间之里的很多道路都被大雪堵塞,使有的学生不能顺利地到达慧音所在的村庄。因此慧音决定换一个能够聚集最多人数的村庄作为新的教学地点。人间之里由N个村庄(编号为1..N)和M条道路组成,道路分为两种一种为单向通行的,一种为双向通行的,分别用1和2来标记。如果存在由村庄A到达村庄B的通路,那么我们认为可以从村庄A到达村庄B,记为(A,B)。当(A,B)和(B,A)同时满足时,我们认为A,B是绝对连通的,记为<A,B>。绝对连通区域是指一个村庄的集合,在这个集合中任意两个村庄X,Y都满足<X,Y>。现在你的任务是,找出最大的绝对连通区域,并将这个绝对连通区域的村庄按编号依次输出。若存在两个最大的,输出字典序最小的,比如当存在1,3,4和2,5,6这两个最大连通区域时,输出的是1,3,4。

输入输出格式

输入格式:

第1行:两个正整数N,M

第2..M+1行:每行三个正整数a,b,t, t = 1表示存在从村庄a到b的单向道路,t = 2表示村庄a,b之间存在双向通行的道路。保证每条道路只出现一次。

输出格式:

第1行: 1个整数,表示最大的绝对连通区域包含的村庄个数。

第2行:若干个整数,依次输出最大的绝对连通区域所包含的村庄编号。

输入输出样例

输入样例#1: 复制
5 5
1 2 1
1 3 2
2 4 2
5 1 2
3 5 1
输出样例#1: 复制
3
1 3 5

说明

对于60%的数据:N <= 200且M <= 10,000

对于100%的数据:N <= 5,000且M <= 50,000

 1 import java.util.ArrayList;
 2 import java.util.Scanner;
 3 
 4 public class Main {
 5     static int n,m;
 6     static int [] dfn,sta,vis,low;
 7     static int top=-1,sum,cnt;
 8     static ArrayList<Integer> v[]  = new ArrayList[50010] ;
 9     static void tarjan(int u) {
10         dfn[u] = low[u] = cnt++;
11         sta[++top] = u;
12         vis[u] = 1;
13         for(int i=0;i<v[u].size();i++) {
14             int to = v[u].get(i);
15             if(dfn[to]==0) {
16                 tarjan(to);
17                 low[u] = Math.min(low[u], low[to]);
18             }
19             else {
20                 if(vis[to]==1) {
21                     low[u] = Math.min(low[u], low[to]);
22                 }
23             }
24             
25         }
26         if(dfn[u]==low[u]) {
27             int num = 0;
28             while(sta[top]!=u) {
29                 num++;
30                 vis[sta[top--]] = 0;
31             }
32             vis[sta[top--]] = 0;
33             num++;
34             if(num>1)
35                 sum++;
36         }
37     }
38     public static void main(String[] args) {
39         Scanner cin = new Scanner(System.in);
40         n = cin.nextInt();
41         m = cin.nextInt();
42         dfn = new int [n+10];
43         sta = new int [n+10];
44         vis = new int [n+10];
45         low = new int [n+10];
46         
47         for(int i=0;i<50010;i++) {
48             v[i] = new ArrayList<Integer>();
49         }
50         for(int i=0;i<m;i++) {
51             int x = cin.nextInt();
52             int y = cin.nextInt();
53             v[x].add(y);
54         }
55         for(int i=1;i<=n;i++) {
56             if(dfn[i]==0)
57                 tarjan(i);
58         }
59         System.out.println(sum);
60     }
61 }

有color版:

 1 import java.util.ArrayList;
 2 import java.util.Scanner;
 3 
 4 public class Main {
 5     static int n,m;
 6     static int top = -1,cnt,sum,ans,ansc;
 7     static int [] dfn,vis,sta,low,color;
 8     static ArrayList<Integer> v[] = new ArrayList[5010];
 9     static void tarjan(int u) {
10         dfn[u] = low[u] = cnt++;
11         vis[u] = 1;
12         sta[++top] = u;
13         for(int i=0;i<v[u].size();i++) {
14             int to = v[u].get(i);
15             if(dfn[to]==0) {
16                 tarjan(to);
17                 low[u] = Math.min(low[u], low[to]);
18             }
19             else {
20                 if(vis[to]==1) {
21                     low[u] = Math.min(low[u], low[to]);
22                 }
23             }
24         }
25         if(dfn[u]==low[u]) {
26             int num = 0;
27             color[u] = ++sum;
28             while(sta[top]!=u) {
29                 num++;
30                 color[sta[top]] = sum;
31                 vis[sta[top--]] = 0;
32             }
33             vis[sta[top--]] = 0;
34             num++;
35             if(num>ans) {
36                 ans = num;
37                 ansc = sum;
38             }
39         }
40     }
41     public static void main(String[] args) {
42         Scanner cin = new Scanner(System.in);
43         n = cin.nextInt();
44         m = cin.nextInt();
45         for(int i=0;i<n+10;i++)
46             v[i] = new ArrayList<>();
47         dfn = new int [n+10];
48         vis = new int [n+10];
49         sta = new int [n+10];
50         low = new int [n+10];
51         color = new int [n+10];
52         for(int i=1;i<=m;i++) {
53             int x,y,op;
54             x = cin.nextInt();
55             y = cin.nextInt();
56             op = cin.nextInt();
57             if(op==1) {
58                 v[x].add(y);
59             }else {
60                 v[x].add(y);
61                 v[y].add(x);
62             }
63         }
64         for(int i=1;i<=n;i++) {
65             if(dfn[i]==0) {
66                 tarjan(i);
67             }
68         }
69         System.out.println(ans);
70         for(int i=1;i<=n;i++) {
71             if(color[i]==ansc) {
72                 System.out.print(i+" ");
73             }
74         }
75     }
76 }

dfs

速算24点

 1 import java.util.Arrays;
 2 import java.util.Scanner;
 3 
 4 public class Main {
 5     static int [] num = new int [5];
 6     static int [] a = new int [5];
 7     static int [] vis = new int [5];
 8     static int flag;
 9     static void check(int sum,int cur,int step) {
10         if(flag==1)
11             return;
12         if(step==3) {
13             if(sum+cur==24||sum-cur==24||sum*cur==24)
14                 flag = 1;
15             if(cur!=0&&sum%cur==0)
16                 if(sum/cur==24)
17                     flag = 1;
18             return;
19         }
20         check(sum+cur, num[step+1], step+1);
21         check(sum-cur, num[step+1], step+1);
22         check(sum*cur, num[step+1], step+1);
23         if(cur!=0&&sum%cur==0)
24             check(sum/cur, num[step+1], step+1);
25         check(sum, cur+num[step+1], step+1);
26         check(sum, cur-num[step+1], step+1);
27         check(sum, cur*num[step+1], step+1);
28         if(num[step+1]!=0&&cur%num[step+1]==0)
29             check(sum, cur/num[step+1], step+1);
30     }
31     static void dfs(int step) {
32         if(step==4) {
33             check(num[0],num[1],1);
34             return;
35         }
36         for(int i=0;i<4;i++) {
37             if(vis[i]==0) {
38                 vis[i] = 1;
39                 num[step] = a[i];
40                 dfs(step+1);
41                 vis[i] = 0;
42             }
43         }
44     }
45     public static void main(String[] args) {
46         Scanner cin = new Scanner(System.in);
47         while(cin.hasNext()) {
48             flag = 0;
49             String ss = cin.nextLine();
50             String [] s = ss.split(" ");
51             for(int i=0;i<4;i++) {
52                 if(s[i].compareTo("0")>=0&&s[i].compareTo("9")<=0)
53                     a[i] = Integer.parseInt(s[i]);
54                 else if(s[i].equals("A"))
55                     a[i] = 1;
56                 else if(s[i].equals("10"))
57                     a[i] = 10;
58                 else if(s[i].equals("J"))
59                     a[i] = 11;
60                 else if(s[i].equals("Q"))
61                     a[i] = 12;
62                 else if(s[i].equals("K"))
63                     a[i] = 13;
64             }
65             Arrays.sort(a, 0,4);
66             for(int i=0;i<5;i++)
67                 vis[i] = 0;
68             dfs(0);
69             if(flag==1)
70                 System.out.println("Yes");
71             else
72                 System.out.println("No");
73         }    
74     }
75 }

单调栈:

题意:给你一个非负整数数组,定义某个区间的参考值为:区间所有元素的和乘以区间最小元素。求该数组中的最大参考值以及对应的区间。
比如说有6个数3 1 6 4 5 2
最大参考值为6,4,5组成的区间,区间最小值为4,参考值为4*(6+5+4)=60
数据范围1<=n<=100000;

 1 import java.util.Scanner;
 2 import java.util.Stack;
 3 
 4 public class Main{
 5     static int n;
 6     static int [] l,r;
 7     static long [] a,sum;
 8     public static void main(String[] args) {
 9         Scanner cin = new Scanner(System.in);
10         n = cin.nextInt();
11         a = new long [n+10];
12         l = new int [n+10];
13         r = new int [n+10];
14         sum = new long [n+10];
15         for(int i=1;i<=n;i++) {
16             a[i] = cin.nextLong();
17             sum[i] = sum[i-1]+a[i];
18         }
19         Stack<Integer>s = new Stack<Integer>();
20         for(int i=1;i<=n;i++) {
21             while(!s.isEmpty()&&a[s.peek()]>=a[i])
22                 s.pop();
23             if(s.isEmpty())
24                 l[i] = 0;
25             else
26                 l[i] = s.peek();
27             s.push(i);
28         }
29         while(!s.isEmpty())
30             s.pop();
31         for(int i=n;i>=1;i--) {
32             while(!s.isEmpty()&&a[s.peek()]>=a[i])
33                 s.pop();
34             if(s.isEmpty())
35                 r[i] = n+1;
36             else
37                 r[i] = s.peek();
38             s.push(i);
39         }
40         int posl = 0,posr = 0;
41         long ans = -1;
42         for(int i=1;i<=n;i++) {
43             //System.out.println("i="+i+" "+l[i]+" "+r[i]);
44             long tmp = a[i]*(sum[r[i]-1]-sum[l[i]]);
45             //System.out.println(tmp);
46             if(tmp>ans) {
47                 ans = tmp;
48                 posl = l[i] + 1;
49                 posr = r[i] - 1;
50             }
51         }
52         System.out.println(ans);
53         System.out.println(posl+" "+posr);
54     }
55 }

 5.20 今天是520鸭!!

简单尺取:

N个数,找到区间和大于等于m的最小区间长度,没有输出0。

2
10 15
5 1 3 5 10 7 4 9 2 8
输出 2 5 11 1 2 3 4 5
输出 3
 1 import java.util.Scanner;
 2 
 3 public class Main {
 4     static int casen,n;
 5     static long m;
 6     static long [] a,sum;
 7     public static void main(String[] args) {
 8         Scanner cin = new Scanner(System.in);
 9         casen = cin.nextInt();
10         while(casen-->0) {
11             n = cin.nextInt();
12             m = cin.nextLong();
13             a = new long [n+10];
14             sum = new long [n+10];
15             for(int i=1;i<=n;i++) {
16                 a[i] = cin.nextLong();
17                 sum[i] = sum[i-1] + a[i];
18             }
19             int l = 1;
20             int r = 1;
21             int flag = 0;
22             int ans = 0x3f3f3f3f;
23             while(r<=n) {
24                 while(r<=n&&sum[r]-sum[l-1]<m) {
25                     r++;
26                 }
27                 if(sum[r]-sum[l-1]>=m) {
28                     flag = 1;
29                     ans = Math.min(ans, r-l+1);
30                 }
31                 l++;
32             }
33             if(flag==1)
34                 System.out.println(ans);
35             else
36                 System.out.println(0);
37         }
38     }
39 }

 二分图匹配:

一共有N个学生跟P门课程,一个学生可以任意选一 门或多门课,问是否达成: 
  1.每个学生选的都是不同的课(即不能有两个学生选同一门课)
  2.每门课都有一个代表(即P门课都被成功选过)
输入为:
第一行一个T代表T组数据
P N(P课程数, N学生数)
接着P行:
第几行代表第几门课程,首先是一个数字k代表对这门课程感兴趣的同学的个数,接下来是k个对这门课程感兴趣同学的编号。
输出为:
若能满足上面两个要求这输出”YES”,否则为”NO”
注意:是课程匹配的学生,学生没课上没事.....
Input
2
3 3
3 1 2 3
2 1 2
1 1
3 3
2 1 3
2 1 3
1 1
Output
YES
NO 
 1 import java.util.Arrays;
 2 import java.util.Scanner;
 3 
 4 public class Main {
 5     static int n,p,k,casen;
 6     static int [][] link;
 7     static int [] match,used;
 8     static boolean find(int x) {
 9         for(int i=1;i<=n;i++) {
10             if(link[x][i]==1&&used[i]==0) {
11                 used[i] = 1;
12                 if(match[i]==-1||find(match[i])) {
13                     match[i] = x;
14                     return true;
15                 }
16             }
17         }
18         return false;
19     }
20     static int hungary() {
21         int ans = 0;
22         Arrays.fill(match, -1);
23         for(int i=1;i<=p;i++) {
24             Arrays.fill(used, 0);
25             if(find(i))
26                 ans++;
27         }
28         return ans;
29     }
30     public static void main(String[] args) {
31         Scanner cin = new Scanner(System.in);
32         casen = cin.nextInt();
33         while(casen-->0) {
34             p = cin.nextInt();
35             n = cin.nextInt();
36             match = new int [310];
37             used = new int [310];
38             link = new int [310][310];
39             for(int i=1;i<=p;i++) {
40                 int k = cin.nextInt();
41                 while(k-->0) {
42                     int x = cin.nextInt();
43                     link[i][x] = 1;
44                 }
45             }
46             int ans = hungary();
47             if(ans==p)
48                 System.out.println("YES");
49             else
50                 System.out.println("NO");
51         }
52     }
53 }

dfs搜索

给出你一个无向图,然后对其中的点去上色, 只能上黑色和白色,要求是黑色点不能相邻(白色可以相邻),问最多能上多少黑色的顶点。

1
6 8
1 2
1 3
2 4
2 5
3 4
3 6
4 6
5 6

Sample Output

3
1 4 5
 1 import java.util.ArrayList;
 2 import java.util.Scanner;
 3 
 4 public class Main{
 5     static int [] vis,res;
 6     static int n,ans;
 7     static ArrayList<Integer> [] v = new ArrayList[110];
 8     static void dfs(int pos,int sum) {
 9         if(pos==n+1) {
10             if(sum>ans) {
11                 ans = sum;
12                 int cnt = 0;
13                 for(int i=1;i<=n;i++) {
14                     if(vis[i]==1)
15                         res[cnt++] = i;
16                 }
17             }
18             return;
19         }
20         int flag = 0;
21         for(int i=0;i<v[pos].size();i++) {
22             if(vis[v[pos].get(i)]==1) {
23                 flag = 1;
24                 break;
25             }
26         }
27         if(flag==0) {
28             vis[pos] = 1;
29             dfs(pos+1, sum+1);
30             vis[pos] = 0;
31         }
32         dfs(pos+1, sum);
33     }
34     public static void main(String[] args) {
35         Scanner cin = new Scanner(System.in);
36         int casen = cin.nextInt();
37         while(casen-->0) {
38             n = cin.nextInt();
39             ans = 0;
40             res = new int [n+10];
41             vis = new int [n+10];
42             for(int i=0;i<n+10;i++)
43                 v[i] = new ArrayList<Integer>();
44             int m = cin.nextInt();
45             for(int i=0;i<m;i++) {
46                 int x = cin.nextInt();
47                 int y = cin.nextInt();
48                 v[x].add(y);
49                 v[y].add(x);
50             }
51             dfs(1, 0);
52             System.out.println(ans);
53             for(int i=0;i<ans;i++)
54                 System.out.print(res[i]+" ");
55         }
56     }
57 }

 05.21

错排

N个数,有M个错排的组合数

 1 import java.util.Scanner;
 2 
 3 public class Main {
 4     static long [][] c = new long [30][30];
 5     static int n,m;
 6     static void init() {
 7         c[0][0] = 1;
 8         for(int i=1;i<=25;i++) {
 9             c[i][0] = 1;
10             for(int j=1;j<=i;j++) {
11                 if(j<=i/2)
12                     c[i][j] = c[i-1][j]+c[i-1][j-1];
13                 else
14                     c[i][j] = c[i][i-j];
15             }
16         }
17     }
18     static void init2() {
19         c[0][0] = 1;
20         for(int i=1;i<=25;i++) {
21             c[i][0] = 1;
22             c[i][i] = 1;
23             for(int j=1;j<i;j++)
24                 c[i][j] = c[i-1][j-1]+c[i-1][j];
25         }
26     }
27     public static void main(String[] args) {
28         Scanner cin = new Scanner(System.in);
29         int casen = cin.nextInt();
30         long [] dp = new long [30];
31         dp[0] = 0;
32         dp[1] = 0;
33         dp[2] = 1;
34         init2();
35         for(int i=3;i<30;i++)
36             dp[i] = (i-1)*(dp[i-1]+dp[i-2]);
37         while(casen-->0) {
38             n = cin.nextInt();
39             m = cin.nextInt();
40             System.out.println(dp[m]*c[n][m]);
41         }
42     }
43 }

kmp:

给定两个数组,问能不能再第一个数组中匹配得到第二个数组,如果可以,那么输出最早匹配的起始位置,否则输出-1

 1 import java.util.Scanner;
 2 
 3 public class Main {
 4     static int n,m;
 5     static int [] s,t;
 6     static int [] next;
 7     static void getnext() {
 8         next[0] = -1;
 9         int i=0,j=-1;
10         while(i<m) {
11             if(j==-1||t[i]==t[j]) {
12                 ++i;
13                 ++j;
14                 next[i] = j;
15             }
16             else
17                 j = next[j];
18         }
19 
20     }
21     static int kmp() {
22         int i=0,j=0;
23         while(i<n&&j<m) {
24             if(j==-1||s[i]==t[j]) {
25                 ++i;
26                 ++j;
27             }
28             else
29                 j = next[j];
30         }
31         if(j==m) {
32             return i-m+1;
33         }
34         else
35             return -1;
36     }
37     public static void main(String[] args) {
38         Scanner cin = new Scanner(System.in);
39         int casen = cin.nextInt();
40         while(casen-->0) {
41             n = cin.nextInt();
42             m = cin.nextInt();
43             s = new int [n+10];
44             t = new int [m+10];
45             next = new int [m+10];
46             for(int i=0;i<n;i++)
47                 s[i] = cin.nextInt();
48             for(int i=0;i<m;i++)
49                 t[i] = cin.nextInt();
50             getnext();
51             System.out.println(kmp());
52         }
53     }
54 }

kmp求循环节:

字符串长度为N,循环节长度为N-next[N],

给一个字符串,问这个字符串是否能由另一个字符串重复R次得到,求R的最大值。

 1 import java.util.Scanner;
 2 
 3 public class Main {
 4     static int n;
 5     static char [] s;
 6     static int [] next;
 7     static void getnext() {
 8         next[0] = -1;
 9         int i=0,j=-1;
10         while(i<n) {
11             if(j==-1||s[i]==s[j]) {
12                 ++i;
13                 ++j;
14                 next[i] = j;
15             }
16             else
17                 j = next[j];
18         }
19     }
20     public static void main(String[] args) {
21         Scanner cin = new Scanner(System.in);
22         int ca = 1;
23         while(cin.hasNext()) {
24             String ss = cin.nextLine();
25             if(ss.equals("."))
26                 break;
27             n = ss.length();
28             next = new int [n+10];
29             s = ss.toCharArray();
30             getnext();
31             
32             int len = n-next[n];
33             if(n%len==0) {
34                 System.out.println(n/len);
35             }else {
36                 System.out.println(1);
37             }
38         }
39     }
40 }

搜索

在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
Input
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
Output
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
Sample Input
2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1
Sample Output
2
1
 1 import java.util.Scanner;
 2 
 3 public class Main {
 4     static int k,n;
 5     static String [] s = new String[10];
 6     static int [] vish = new int[10];
 7     static int [] viss = new int[10];
 8     static char[][] a = new char[10][10];
 9     static int ans = 0;
10     static void dfs(int x,int step) {
11         if(step>=k) {
12             ans++;
13             return;
14         }
15         for(int i=x;i<n;i++) {
16             for(int j=0;j<n;j++) {
17                 if(vish[i]==0&&viss[j]==0&&a[i][j]=='#') {
18                     viss[j] = 1;
19                     vish[i] = 1;
20                     dfs(i+1, step+1);
21                     vish[i] = 0;
22                     viss[j] = 0;
23                 }
24             }
25         }
26     }
27     public static void main(String[] args) {
28         Scanner cin = new Scanner(System.in);
29         while(cin.hasNext()) {
30             ans = 0;
31             n = cin.nextInt();
32             k = cin.nextInt();
33             if(n==-1&&k==-1)
34                 break;
35             for(int i=0;i<vish.length;i++)
36                 vish[i] = 0;
37             for(int i=0;i<viss.length;i++)
38                 viss[i] = 0;
39             for(int i=0;i<n;i++)
40                 s[i] = cin.next();
41             for(int i=0;i<n;i++) {
42                 for(int j=0;j<n;j++) {
43                     a[i][j] = s[i].charAt(j);
44                 }
45             }//
46             dfs(0, 0);
47             System.out.println(ans);
48         }
49         
50     }
51 }

 05.22

LCA:

求树上两点最短距离

 1 import java.util.Arrays;
 2 import java.util.Scanner;
 3 class node{
 4     int to;
 5     int val;
 6     int next;
 7 }
 8 public class Main {
 9     static int n,q;
10     static int [] head,dis,depth;
11     static node [] e;
12     static int cnt = 0;
13     static int [][] f;
14     static void add(int x,int y,int w) {
15         e[cnt].to = y;
16         e[cnt].val = w;
17         e[cnt].next = head[x];
18         head[x] = cnt++;
19     }
20     static void dfs(int x,int fa) {
21         f[x][0] = fa;
22         for(int i=head[x];i!=-1;i=e[i].next) {
23             int to = e[i].to;
24             if(to!=fa) {
25                 dis[to] = dis[x]+e[i].val;
26                 depth[to] = depth[x] + 1;
27                 dfs(to, x);
28             }
29         }
30     }
31     static void init() {
32         depth[1] = 1;
33         dis[1] = 0;
34         dfs(1, 0);
35         //设fa[i][j]表示i结点的第2^j个祖先,显然有
36         for(int j=1;(1<<j)<=n;j++) {
37             for(int i=1;i<=n;i++) {
38                 //System.out.println("i="+i+" j-1="+(j-1)+f[i][j-1]);
39                 f[i][j] = f[f[i][j-1]][j-1];
40             }
41         }
42     }
43     static int lca(int x,int y) {
44         if(depth[x]<depth[y]) {
45             int a = x ;
46             x = y;
47             y = a;
48         }
49         for(int i=20;i>=0;i--) {
50             if(depth[f[x][i]]>=depth[y]) {
51                 x = f[x][i];
52                 if(x==y)
53                     return x;
54             }
55         }
56         for(int i=20;i>=0;i--) {
57             if(f[x][i]!=f[y][i]) {
58                 x = f[x][i];
59                 y = f[y][i];
60             }
61         }
62         return f[x][0];
63     }
64     public static void main(String[] args) {
65         Scanner cin = new Scanner(System.in);
66         int casen = cin.nextInt();
67         while(casen-->0) {
68             cnt = 0;
69             n = cin.nextInt();
70             q = cin.nextInt();
71             f = new int [40000+10][21];
72             e = new node[160000+10];
73             head = new int [40000+10];
74             dis = new int [40000+10];
75             depth = new int [40000+10];
76             Arrays.fill(head, -1);
77             for(int i=0;i<=n<<2;i++)
78                 e[i] = new node();
79             for(int i=0;i<n-1;i++) {
80                 int x = cin.nextInt();
81                 int y = cin.nextInt();
82                 int w = cin.nextInt();
83                 add(x, y, w);
84                 add(y, x, w);
85             }
86             init();
87             
88             while(q-->0) {
89                 int x = cin.nextInt();
90                 int y = cin.nextInt();
91                 System.out.println(dis[x]+dis[y]-2*dis[lca(x, y)]);
92                 
93             }
94             System.out.println();
95         }
96     }
97 }
http://codevs.cn/problem/1036/
1
#include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=3e4+10; 7 int path[maxn]; 8 struct node{ 9 int to; 10 int val; 11 int nex; 12 }e[maxn<<2]; 13 int f[maxn][22]; 14 int head[maxn],dis[maxn],depth[maxn]; 15 int n,cnt; 16 void add(int x,int y,int w){ 17 e[cnt].to=y; 18 e[cnt].val=w; 19 e[cnt].nex=head[x]; 20 head[x]=cnt++; 21 } 22 void dfs(int x,int fa) 23 { 24 f[x][0]=fa; 25 for(int i=head[x];i!=-1;i=e[i].nex) 26 { 27 int to=e[i].to; 28 if(to!=fa) 29 { 30 dis[to]=dis[x]+e[i].val; 31 depth[to]=depth[x]+1; 32 dfs(to,x); 33 } 34 } 35 } 36 void init() 37 { 38 depth[1]=1; 39 dis[1]=0; 40 dfs(1,0); 41 for(int j=1;(1<<j)<=n;j++) 42 { 43 for(int i=1;i<=n;i++) 44 { 45 f[i][j]=f[f[i][j-1]][j-1]; 46 } 47 } 48 } 49 int lca(int x,int y) 50 { 51 if(depth[x]<depth[y]) 52 { 53 swap(x,y); 54 } 55 int dis=depth[x]-depth[y]; 56 for(int i=0;i<=20;i++) 57 { 58 if((1<<i)&dis) 59 { 60 x=f[x][i]; 61 } 62 } 63 if(x==y) 64 return x; 65 for(int i=20;i>=0;i--) 66 { 67 if(f[x][i]!=f[y][i]) 68 { 69 x=f[x][i]; 70 y=f[y][i]; 71 } 72 } 73 return f[x][0]; 74 } 75 int main() 76 { 77 scanf("%d",&n);memset(head,-1,sizeof(head)); 78 for(int i=0;i<n-1;i++) 79 { 80 int x,y; 81 scanf("%d%d",&x,&y); 82 add(x,y,1); 83 add(y,x,1); 84 } 85 init(); 86 int m; 87 cin>>m; 88 89 for(int i=0;i<m;i++) 90 { 91 scanf("%d",&path[i]); 92 } 93 int ans=0; 94 for(int i=0;i<m-1;i++) 95 { 96 ans+=dis[path[i]]+dis[path[i+1]]-2*dis[lca(path[i],path[i+1])]; 97 } 98 printf("%d ",ans); 99 }

 05.23

树的直径

求树上相距最远两点的距离

 1 import java.util.ArrayDeque;
 2 import java.util.Arrays;
 3 import java.util.Scanner;
 4 class node{
 5     int to;
 6     int w;
 7     int next;
 8 }
 9 public class Main {
10     static node [] e = new node[100000];
11     static int [] head = new int [10000];
12     static int [] dis = new int [10000];
13     static int [] vis = new int [10000];
14     static int cnt = 0,ed,sum;
15     static void add(int x,int y,int w) {
16         e[cnt].to = y;
17         e[cnt].w = w;
18         e[cnt].next = head[x];
19         head[x] = cnt++;
20         
21     }
22     static void bfs(int x) {
23         ArrayDeque<Integer> q = new ArrayDeque<Integer>();
24         q.offer(x);
25         Arrays.fill(vis, 0);
26         Arrays.fill(dis, 0);
27         vis[x] = 1;
28         sum = 0;
29         while(!q.isEmpty()) {
30             int pos = q.poll();
31             for(int i=head[pos];i!=-1;i=e[i].next) {
32                 int to = e[i].to;
33                 if(vis[to]==0) {
34                     vis[to] = 1;
35                     dis[to] = dis[pos] + e[i].w;
36                     if(sum<dis[to]) {
37                         sum = dis[to];
38                         ed = to;
39                     }
40                     q.offer(to);
41                 }
42             }
43         }
44     }
45     public static void main(String[] args) {
46         Scanner cin = new Scanner(System.in);
47         for(int i=0;i<100000;i++)
48             e[i] = new node();
49         Arrays.fill(head, -1);
50         while(cin.hasNext()) {
51             int x = cin.nextInt();
52             int y = cin.nextInt();
53             int w = cin.nextInt();
54             add(x, y, w);
55             add(y, x, w);
56         }
57         bfs(1);
58         bfs(ed);
59     
60         System.out.println(sum);
61     }
62 }

拓扑排序:

 1 import java.util.ArrayDeque;
 2 import java.util.Arrays;
 3 import java.util.PriorityQueue;
 4 import java.util.Scanner;
 5 class node{
 6     int to;
 7     int nex;
 8 }
 9 public class Main{
10     static int n,m,cnt,t;
11     static node [] e;
12     static int [] head,in,ans;
13     static void add(int x,int y) {
14         e[cnt].to = y;
15         e[cnt].nex = head[x];
16         head[x] = cnt++;
17     }
18     static void topu() {
19         PriorityQueue<Integer>q = new PriorityQueue<Integer>();
20         for(int i=1;i<=n;i++) {
21             if(in[i]==0)
22                 q.offer(i);
23         }
24         t = 0;
25         while(!q.isEmpty()) {
26             int pos = q.poll();
27             ans[t++] = pos;
28             for(int i=head[pos];i!=-1;i=e[i].nex){
29                 int to = e[i].to;
30                 in[to]--;
31                 if(in[to]==0)
32                     q.offer(to);
33             }
34         }
35     }
36     public static void main(String[] args) {
37         Scanner cin = new Scanner(System.in);
38         while(cin.hasNext()) {
39             cnt = 0;
40             t = 0;
41             n = cin.nextInt();
42             m = cin.nextInt();
43             e = new node[m+10];
44             for(int i=0;i<m+5;i++)
45                 e[i] = new node();
46             head = new int [n+10];
47             in = new int [n+10];
48             ans = new int [n+10];
49             Arrays.fill(head, -1);
50             for(int i=0;i<m;i++) {
51                 int x = cin.nextInt();
52                 int y = cin.nextInt();
53                 add(x, y);
54                 in[y]++;
55             }
56             topu();
57             for(int i=0;i<t-1;i++)
58                 System.out.print(ans[i]+" ");
59             System.out.println(ans[t-1]);
60         }
61     }
62 }

 manacher

import java.util.Collection;
import java.util.PriorityQueue;
import java.util.Scanner;

public class Main{
    static String s,t;
    static int [] r;
    static int manacher(int n) {
        int  cnt = 0;
        t = "";
        t+="$#";
        for(int i=0;i<n;i++) {
            t+=s.charAt(i);
            t+="#";
        }
        //System.out.println(t);
        int pos = 0,rx = 0,ans = 1;
        cnt = t.length();;
        for(int i=1;i<cnt;i++) {
            r[i]=(rx>i)?Math.min(r[2*pos-i], rx-i):1;
            
            while(i-r[i]>=0&&i+r[i]<cnt&&t.charAt(i-r[i])==t.charAt(i+r[i]))
                r[i]++;
            if(rx<i+r[i]) {
                rx = i+r[i];
                pos = i;
            }
            if(ans<r[i] - 1 )
                ans = r[i]-1;
        }
        return ans;
    }
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        while(cin.hasNext()) {
            s = cin.next();
            if(s.equals("END"))
                break;
            r = new int [1000000*2+10];
            
            System.out.println(manacher(s.length()));
        }
    }
}

一些JAVA知识点:

import  java.util.*;

public class xx {
    
    
    static class cmp implements Comparator<LLong>{
        @Override
        public int compare(LLong o1, LLong o2) {
            return (int) (o2.val - o1.val);
        }
    }
    
    static List<LLong> list = new ArrayList<LLong>();
    static Queue<LLong> qu = new LinkedList<LLong>();
    static Deque<Integer> quee = new LinkedList<Integer>();
    static PriorityQueue<LLong> que = new PriorityQueue<LLong>();
    static Set<LLong> set = new TreeSet<LLong>(); 
    static Map<Integer,Set<Integer>> map = new TreeMap<Integer, Set<Integer>>();
    
    static class LLong implements Comparable<LLong>{
        int x;
        long val;
        String s;
        
        @Override
        public int compareTo(LLong o) {
            if(this.x == o.x)
                return (int) (this.val - o.val);
            else if(this.x >= o.x)
                return (int) (o.val - this.val);
            else
                return (this.s).compareTo(o.s); 
                
        }
    }
    
    public static void main(String[] args) {
        
        Collections.sort(list, new cmp()); 
        
        Collections.sort(list, new Comparator<LLong>() {
            @Override
            public int compare(LLong o1, LLong o2) {
                return (int) (o2.val-o1.val);
            }
        });
        
        
    }
}
Input输入数据首先包含一个正整数C,表示有C组测试用例,每组测试用例的第一行是两个整数n和m(1<=n<=100, 1<=m<=100),分别表示经费的金额和大米的种类,然后是m行数据,每行包含3个数p,h和c(1<=p<=20,1<=h<=200,1<=c<=20),分别表示每袋的价格、每袋的重量以及对应种类大米的袋数。Output对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。Sample Input
1
8 2
2 100 4
4 100 2
Sample Output
400
 1 #include<iostream>  
 2 #include<stdio.h>  
 3 #include<algorithm>  
 4 #include<cstring>   
 5 using namespace std;  
 6 int c[11000],w[11000],num[11000];  
 7 int dp[11000];  
 8 int m,n,tip;
 9 int casen;
10 void ZeroOnePack(int c, int w)  
11 {  
12     for(int v =n; v >=c; v--)  
13     {  
14         dp[v] = max(dp[v],dp[v-c]+w);  
15     }  
16 }  
17   
18 void CompletePack(int c, int w)  
19 {  
20     for(int v = c; v <= n; v++)  
21     {  
22         dp[v] = max(dp[v],dp[v-c]+w);  
23     }  
24 }  
25   
26 void MultiplePack(int c, int w, int num)  
27 {  
28     if(c*num>=n)  
29     {  
30         CompletePack(c,w);  
31     }  
32     else  
33     {  
34         int k = 1;  
35         while(k < num)  
36         {  
37             ZeroOnePack(k*c, k*w);  
38             num -= k;  
39             k <<= 1;  
40         }  
41         ZeroOnePack(num*c, num*w);  
42     }  
43 }  
44 int main()  
45 {  
46         scanf("%d",&casen);
47         while(casen--)
48         { 
49         scanf("%d%d",&n,&m);  
50         for(int i = 1; i <=m; i++)  
51         {  
52             scanf("%d%d%d",&c[i], &w[i], &num[i]);  
53         }  
54         memset(dp,0,sizeof(dp));  
55         for(int i = 1; i <=m; i++)  
56         {  
57             MultiplePack(c[i],w[i],num[i]);  
58         }  
59         printf("%d
",dp[n]);  
60         }
61     return 0;  
62 }  
原文地址:https://www.cnblogs.com/1013star/p/10877988.html