题意:每次优先按权重最小的边dfs,不重复搜一个节点,问从那些点作为根节点搜索得到的路径与最小生成树一样?
思路见官方题解 Codeforces Round #808 Editorial - Codeforces
主要是先得到最小生成树,每条多余的边能排除一些最小生成树的点.比如上图多余的边是(u,v),就能把u,v以下的点都排除了.
但是怎么在O(n)复杂度得到这些点?,就要用到差分思想,参考树上差分详解 - TEoS - 博客园
差分思想就是用一些特殊点代表一种累计效果.最后再求一次前缀和. 不同情况下细节略有不同.
改题中还需要求lca
- import java.util.*;
- import java.io.*;
-
- public class Main {
- public static void main(String args[]) {new Main().run();}
-
- FastReader in = new FastReader();
- PrintWriter out = new PrintWriter(System.out);
- void run() {
- work();
- out.flush();
- }
- long mod=998244353;
- long gcd(long a,long b) {
- return a==0?b:gcd(b%a,a);
- }
- final long inf=Long.MAX_VALUE/3;
- ArrayList
[] graph; - int[] id;
- int[][] dp;
- int[] deep;
- int[] rec;
- void work(){
- int n=ni(),m=ni();
- graph=new ArrayList[n];
- deep=new int[n];
- dp=new int[n][20];
- id=new int[n];
- for(int i=0;i
- graph[i]=new ArrayList<>();
- id[i]=i;
- }
- rec=new int[n];//差分
- int[][] edge=new int[m-n+1][];
- for(int i=0,j=0;i
- int s=ni()-1,e=ni()-1;
- if(union(s,e)){
- edge[j++]=new int[]{s,e};
- }else{
- graph[s].add(e);
- graph[e].add(s);
- }
- }
- dfs(0,-1);
- for(int i=0;i
- int n1=edge[i][0],n2=edge[i][1];
- int lca = lca(n1, n2);
- if(lca==n1){
- int cur=n2;
- for(int j=19;j>=0;j--){
- if(dp[cur][j]!=-1&&deep[dp[cur][j]]>deep[n1]){
- cur=dp[cur][j];
- }
- }
- rec[cur]++;
- rec[n2]--;
- }else if(lca==n2){
- int cur=n1;
- for(int j=19;j>=0;j--){
- if(dp[cur][j]!=-1&&deep[dp[cur][j]]>deep[n2]){
- cur=dp[cur][j];
- }
- }
- rec[cur]++;
- rec[n1]--;
- }else{
- rec[0]++;
- rec[n1]--;
- rec[n2]--;
- }
- }
- dfs2(0,-1);
- StringBuilder sb=new StringBuilder();
- for(int i=0;i
- if(rec[i]>0)sb.append(0);
- else sb.append(1);
- }
- out.println(sb.toString());
- }
-
- private void dfs2(int node, int pre) {
- if(pre!=-1){
- rec[node]+=rec[pre];
- }
- for(int nn:graph[node]){
- if(nn!=pre){
- dfs2(nn,node);
- }
- }
- }
-
- private void dfs(int node, int pre) {
- dp[node][0]=pre;
- if(pre!=-1){
- deep[node]=deep[pre]+1;
- }
- for(int i=1;i<20&&dp[node][i-1]!=-1;i++){
- dp[node][i]=dp[dp[node][i-1]][i-1];
- }
- for(int nn:graph[node]){
- if(nn!=pre){
- dfs(nn,node);
- }
- }
- }
-
- private int lca(int n1,int n2){
- int d1=deep[n1],d2=deep[n2];
- int d=Math.min(d1,d2);
- int cur1=n1,cur2=n2;
- for(int i=19;i>=0;i--){
- if(dp[cur1][i]!=-1&&deep[dp[cur1][i]]>=d){
- cur1=dp[cur1][i];
- }
- }
- for(int i=19;i>=0;i--){
- if(dp[cur2][i]!=-1&&deep[dp[cur2][i]]>=d){
- cur2=dp[cur2][i];
- }
- }
- if(cur1==cur2)return cur1;
- for(int i=19;i>=0;i--){
- if(dp[cur1][i]!=dp[cur2][i]){
- cur1=dp[cur1][i];
- cur2=dp[cur2][i];
- }
- }
- return dp[cur1][0];
- }
-
- boolean union(int q,int p){
- int proot = find(p);
- int qroot = find(q);
- if(proot==qroot){
- return true;
- }
- id[proot]=qroot;
- return false;
- }
-
- int find(int q){
- if(q!=id[q]){
- id[q]=find(id[q]);
- }
- return id[q];
- }
- @SuppressWarnings("unused")
- private ArrayList
[] ng(int n, int m) { - ArrayList
[] graph=(ArrayList[])new ArrayList[n]; - for(int i=0;i
- graph[i]=new ArrayList<>();
- }
- for(int i=1;i<=m;i++) {
- int s=in.nextInt()-1,e=in.nextInt()-1;
- graph[s].add(e);
- graph[e].add(s);
- }
- return graph;
- }
-
- private ArrayList<long[]>[] ngw(int n, int m) {
- ArrayList<long[]>[] graph=(ArrayList<long[]>[])new ArrayList[n];
- for(int i=0;i
- graph[i]=new ArrayList<>();
- }
- for(int i=1;i<=m;i++) {
- long s=in.nextLong()-1,e=in.nextLong()-1,w=in.nextLong();
- graph[(int)s].add(new long[] {e,w});
- graph[(int)e].add(new long[] {s,w});
- }
- return graph;
- }
-
- private int ni() {
- return in.nextInt();
- }
-
- private long nl() {
- return in.nextLong();
- }
- private double nd() {
- return in.nextDouble();
- }
- private String ns() {
- return in.next();
- }
-
- private long[] na(int n) {
- long[] A=new long[n];
- for(int i=0;i
- A[i]=in.nextLong();
- }
- return A;
- }
-
- private int[] nia(int n) {
- int[] A=new int[n];
- for(int i=0;i
- A[i]=in.nextInt();
- }
- return A;
- }
- }
-
- class FastReader
- {
- BufferedReader br;
- StringTokenizer st;
- InputStreamReader input;//no buffer
- public FastReader()
- {
- br=new BufferedReader(new InputStreamReader(System.in));
- }
-
- public FastReader(boolean isBuffer)
- {
- if(!isBuffer){
- input=new InputStreamReader(System.in);
- }else{
- br=new BufferedReader(new InputStreamReader(System.in));
- }
- }
-
- public boolean hasNext(){
- try{
- String s=br.readLine();
- if(s==null){
- return false;
- }
- st=new StringTokenizer(s);
- }catch(IOException e){
- e.printStackTrace();
- }
- return true;
- }
-
- public String next()
- {
- if(input!=null){
- try {
- StringBuilder sb=new StringBuilder();
- int ch=input.read();
- while(ch=='\n'||ch=='\r'||ch==32){
- ch=input.read();
- }
- while(ch!='\n'&&ch!='\r'&&ch!=32){
- sb.append((char)ch);
- ch=input.read();
- }
- return sb.toString();
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- while(st==null || !st.hasMoreElements())//回车,空行情况
- {
- try {
- st = new StringTokenizer(br.readLine());
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return st.nextToken();
- }
-
- public int nextInt()
- {
- return (int)nextLong();
- }
-
- public long nextLong() {
- try {
- if(input!=null){
- long ret=0;
- int b=input.read();
- while(b<'0'||b>'9'){
- b=input.read();
- }
- while(b>='0'&&b<='9'){
- ret=ret*10+(b-'0');
- b=input.read();
- }
- return ret;
- }
- }catch (Exception e){
- e.printStackTrace();
- }
- return Long.parseLong(next());
- }
-
- public double nextDouble()
- {
- return Double.parseDouble(next());
- }
- }
-
相关阅读:
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