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行:若干个整数,依次输出最大的绝对连通区域所包含的村庄编号。
输入输出样例
说明
对于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 }
二分图匹配:
2 3 3 3 1 2 3 2 1 2 1 1 3 3 2 1 3 2 1 3 1 1Output
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 }
搜索
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
2 1 #. .# 4 4 ...# ..#. .#.. #... -1 -1Sample 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\n",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); } }); } }
1 8 2 2 100 4 4 100 2Sample 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\n",dp[n]); 60 } 61 return 0; 62 }