• CF1707C - DFS Trees (树上差分)


    题意:每次优先按权重最小的边dfs,不重复搜一个节点,问从那些点作为根节点搜索得到的路径与最小生成树一样?

    Problem - C - Codeforces

    思路见官方题解 Codeforces Round #808 Editorial - Codeforces

    主要是先得到最小生成树,每条多余的边能排除一些最小生成树的点.比如上图多余的边是(u,v),就能把u,v以下的点都排除了.

    但是怎么在O(n)复杂度得到这些点?,就要用到差分思想,参考树上差分详解 - TEoS - 博客园

    差分思想就是用一些特殊点代表一种累计效果.最后再求一次前缀和. 不同情况下细节略有不同.

     改题中还需要求lca

    1. import java.util.*;
    2. import java.io.*;
    3. public class Main {
    4. public static void main(String args[]) {new Main().run();}
    5. FastReader in = new FastReader();
    6. PrintWriter out = new PrintWriter(System.out);
    7. void run() {
    8. work();
    9. out.flush();
    10. }
    11. long mod=998244353;
    12. long gcd(long a,long b) {
    13. return a==0?b:gcd(b%a,a);
    14. }
    15. final long inf=Long.MAX_VALUE/3;
    16. ArrayList[] graph;
    17. int[] id;
    18. int[][] dp;
    19. int[] deep;
    20. int[] rec;
    21. void work(){
    22. int n=ni(),m=ni();
    23. graph=new ArrayList[n];
    24. deep=new int[n];
    25. dp=new int[n][20];
    26. id=new int[n];
    27. for(int i=0;i
    28. graph[i]=new ArrayList<>();
    29. id[i]=i;
    30. }
    31. rec=new int[n];//差分
    32. int[][] edge=new int[m-n+1][];
    33. for(int i=0,j=0;i
    34. int s=ni()-1,e=ni()-1;
    35. if(union(s,e)){
    36. edge[j++]=new int[]{s,e};
    37. }else{
    38. graph[s].add(e);
    39. graph[e].add(s);
    40. }
    41. }
    42. dfs(0,-1);
    43. for(int i=0;i
    44. int n1=edge[i][0],n2=edge[i][1];
    45. int lca = lca(n1, n2);
    46. if(lca==n1){
    47. int cur=n2;
    48. for(int j=19;j>=0;j--){
    49. if(dp[cur][j]!=-1&&deep[dp[cur][j]]>deep[n1]){
    50. cur=dp[cur][j];
    51. }
    52. }
    53. rec[cur]++;
    54. rec[n2]--;
    55. }else if(lca==n2){
    56. int cur=n1;
    57. for(int j=19;j>=0;j--){
    58. if(dp[cur][j]!=-1&&deep[dp[cur][j]]>deep[n2]){
    59. cur=dp[cur][j];
    60. }
    61. }
    62. rec[cur]++;
    63. rec[n1]--;
    64. }else{
    65. rec[0]++;
    66. rec[n1]--;
    67. rec[n2]--;
    68. }
    69. }
    70. dfs2(0,-1);
    71. StringBuilder sb=new StringBuilder();
    72. for(int i=0;i
    73. if(rec[i]>0)sb.append(0);
    74. else sb.append(1);
    75. }
    76. out.println(sb.toString());
    77. }
    78. private void dfs2(int node, int pre) {
    79. if(pre!=-1){
    80. rec[node]+=rec[pre];
    81. }
    82. for(int nn:graph[node]){
    83. if(nn!=pre){
    84. dfs2(nn,node);
    85. }
    86. }
    87. }
    88. private void dfs(int node, int pre) {
    89. dp[node][0]=pre;
    90. if(pre!=-1){
    91. deep[node]=deep[pre]+1;
    92. }
    93. for(int i=1;i<20&&dp[node][i-1]!=-1;i++){
    94. dp[node][i]=dp[dp[node][i-1]][i-1];
    95. }
    96. for(int nn:graph[node]){
    97. if(nn!=pre){
    98. dfs(nn,node);
    99. }
    100. }
    101. }
    102. private int lca(int n1,int n2){
    103. int d1=deep[n1],d2=deep[n2];
    104. int d=Math.min(d1,d2);
    105. int cur1=n1,cur2=n2;
    106. for(int i=19;i>=0;i--){
    107. if(dp[cur1][i]!=-1&&deep[dp[cur1][i]]>=d){
    108. cur1=dp[cur1][i];
    109. }
    110. }
    111. for(int i=19;i>=0;i--){
    112. if(dp[cur2][i]!=-1&&deep[dp[cur2][i]]>=d){
    113. cur2=dp[cur2][i];
    114. }
    115. }
    116. if(cur1==cur2)return cur1;
    117. for(int i=19;i>=0;i--){
    118. if(dp[cur1][i]!=dp[cur2][i]){
    119. cur1=dp[cur1][i];
    120. cur2=dp[cur2][i];
    121. }
    122. }
    123. return dp[cur1][0];
    124. }
    125. boolean union(int q,int p){
    126. int proot = find(p);
    127. int qroot = find(q);
    128. if(proot==qroot){
    129. return true;
    130. }
    131. id[proot]=qroot;
    132. return false;
    133. }
    134. int find(int q){
    135. if(q!=id[q]){
    136. id[q]=find(id[q]);
    137. }
    138. return id[q];
    139. }
    140. @SuppressWarnings("unused")
    141. private ArrayList[] ng(int n, int m) {
    142. ArrayList[] graph=(ArrayList[])new ArrayList[n];
    143. for(int i=0;i
    144. graph[i]=new ArrayList<>();
    145. }
    146. for(int i=1;i<=m;i++) {
    147. int s=in.nextInt()-1,e=in.nextInt()-1;
    148. graph[s].add(e);
    149. graph[e].add(s);
    150. }
    151. return graph;
    152. }
    153. private ArrayList<long[]>[] ngw(int n, int m) {
    154. ArrayList<long[]>[] graph=(ArrayList<long[]>[])new ArrayList[n];
    155. for(int i=0;i
    156. graph[i]=new ArrayList<>();
    157. }
    158. for(int i=1;i<=m;i++) {
    159. long s=in.nextLong()-1,e=in.nextLong()-1,w=in.nextLong();
    160. graph[(int)s].add(new long[] {e,w});
    161. graph[(int)e].add(new long[] {s,w});
    162. }
    163. return graph;
    164. }
    165. private int ni() {
    166. return in.nextInt();
    167. }
    168. private long nl() {
    169. return in.nextLong();
    170. }
    171. private double nd() {
    172. return in.nextDouble();
    173. }
    174. private String ns() {
    175. return in.next();
    176. }
    177. private long[] na(int n) {
    178. long[] A=new long[n];
    179. for(int i=0;i
    180. A[i]=in.nextLong();
    181. }
    182. return A;
    183. }
    184. private int[] nia(int n) {
    185. int[] A=new int[n];
    186. for(int i=0;i
    187. A[i]=in.nextInt();
    188. }
    189. return A;
    190. }
    191. }
    192. class FastReader
    193. {
    194. BufferedReader br;
    195. StringTokenizer st;
    196. InputStreamReader input;//no buffer
    197. public FastReader()
    198. {
    199. br=new BufferedReader(new InputStreamReader(System.in));
    200. }
    201. public FastReader(boolean isBuffer)
    202. {
    203. if(!isBuffer){
    204. input=new InputStreamReader(System.in);
    205. }else{
    206. br=new BufferedReader(new InputStreamReader(System.in));
    207. }
    208. }
    209. public boolean hasNext(){
    210. try{
    211. String s=br.readLine();
    212. if(s==null){
    213. return false;
    214. }
    215. st=new StringTokenizer(s);
    216. }catch(IOException e){
    217. e.printStackTrace();
    218. }
    219. return true;
    220. }
    221. public String next()
    222. {
    223. if(input!=null){
    224. try {
    225. StringBuilder sb=new StringBuilder();
    226. int ch=input.read();
    227. while(ch=='\n'||ch=='\r'||ch==32){
    228. ch=input.read();
    229. }
    230. while(ch!='\n'&&ch!='\r'&&ch!=32){
    231. sb.append((char)ch);
    232. ch=input.read();
    233. }
    234. return sb.toString();
    235. }catch (Exception e){
    236. e.printStackTrace();
    237. }
    238. }
    239. while(st==null || !st.hasMoreElements())//回车,空行情况
    240. {
    241. try {
    242. st = new StringTokenizer(br.readLine());
    243. } catch (IOException e) {
    244. e.printStackTrace();
    245. }
    246. }
    247. return st.nextToken();
    248. }
    249. public int nextInt()
    250. {
    251. return (int)nextLong();
    252. }
    253. public long nextLong() {
    254. try {
    255. if(input!=null){
    256. long ret=0;
    257. int b=input.read();
    258. while(b<'0'||b>'9'){
    259. b=input.read();
    260. }
    261. while(b>='0'&&b<='9'){
    262. ret=ret*10+(b-'0');
    263. b=input.read();
    264. }
    265. return ret;
    266. }
    267. }catch (Exception e){
    268. e.printStackTrace();
    269. }
    270. return Long.parseLong(next());
    271. }
    272. public double nextDouble()
    273. {
    274. return Double.parseDouble(next());
    275. }
    276. }

  • 相关阅读:
    Redis入门:Redis持久化策略RDB&AOF简介
    9月客户文章盘点——累计IF 103.2
    持续更新ChatGPT商业运营网站程序源码,支持Midjourney绘画Dalle3绘画,多种语音对话+suno-ai音乐生成+TTS语音对话+支持GPTs
    yolov5自动训练/预测-小白教程
    Python+requests+pytest+excel+allure 接口自动化测试实战
    【Python3】列表字典集合元组
    小型框架集合
    性能调优——小小的log大大的坑
    基于C++QT框架的地铁换乘可视化查询系统
    企业电子招投标采购系统——功能模块&功能描述+数字化采购管理 采购招投标
  • 原文地址:https://blog.csdn.net/yaoct/article/details/126304048