zoukankan      html  css  js  c++  java
  • CF521E Cycling City DFS树+暴力

    如果只要求判断有没有解的话很好做:以条树边被两条非树边覆盖即可.    

    输出方案的话可以考虑碰到一条非树边就暴力覆盖.   

    如果覆盖的过程中发现一条边已经被覆盖了就输出结果.   

    由于一条边只能被一种非树边覆盖,所以复杂度均摊下来是 $O(n)$ 的.  

    然后我们就得到两条路径 $(a,b)$ 与 $(c,d)$,$dep[a] leqslant dep[c]$         

    1:$a ightarrow b ightarrow lca$ 

    2:$c ightarrow d ightarrow lca$  

    3:$c ightarrow lca$  

    然后求非树边那里要注意一下:点 $y$ 必须为 $x$ 的祖先,所以开一个 ins 数组来判断 $x$ 是否在 $y$ 的子树中.   

    code:  

    #include <stack>
    #include <cstdio>   
    #include <cstring>
    #include <algorithm>
    #define N 200009    
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin)  
    using namespace std; 
    int n,m,edges; 
    stack<int>sta;   
    int fa[N],dep[N],mx[N],my[N],ins[N]; 
    int hd[N],to[N<<1],nex[N<<1],vis[N]; 
    void add(int u,int v) { 
        nex[++edges]=hd[u],hd[u]=edges;
        to[edges]=v;  
    } 
    int get_lca(int x,int y) { 
        if(dep[x]!=dep[y]) { 
            if(dep[x]>dep[y]) swap(x,y);                 
            while(dep[y]>dep[x]) y=fa[y];        
        }    
        if(x==y) return x;    
        while(x!=y) x=fa[x],y=fa[y];  
        return x;   
    }
    void calc(int a,int b,int c,int d) { 
        if(dep[a]>dep[c]) { 
            swap(a,c);  
            swap(b,d); 
        }                       
    
        printf("YES
    ");  
        int lca=get_lca(b,d);     
        sta.push(lca);         
        for(int i=lca;i!=c;i=fa[i]) sta.push(fa[i]);   
        printf("%d ",sta.size());   
        while(!sta.empty()) printf("%d ",sta.top()),sta.pop();   
        printf("
    ");  
    
        printf("%d ",dep[c]-dep[a]+dep[b]-dep[lca]+2);    
        printf("%d ",c);  
        for(int i=c;i!=a;i=fa[i]) printf("%d ",fa[i]);   
        printf("%d ",b);  
        for(int i=b;i!=lca;i=fa[i]) printf("%d ",fa[i]);  
        printf("
    ");   
    
        printf("%d ",dep[d]-dep[lca]+2);   
        printf("%d %d ",c,d);   
        for(int i=d;i!=lca;i=fa[i]) printf("%d ",fa[i]);   
        printf("
    ");  
    }
    void dfs(int x,int ff) { 
        vis[x]=1;   
        ins[x]=1;  
        fa[x]=ff;   
        dep[x]=dep[ff]+1;                                   
        for(int i=hd[x];i;i=nex[i]) { 
            int y=to[i];
            if(y==ff) continue;
            if(!vis[y]) {
                dfs(y,x);           
            }
            else if(ins[y]) {       
                for(int j=x;j!=y;j=fa[j]){      
                    if(mx[j]) {          
                        calc(mx[j],my[j],y,x);   
                        exit(0);    
                    }
                    else { 
                        mx[j]=y,my[j]=x;  
                    }
                }
            }
        }
        ins[x]=0;  
    }   
    int main() {  
        // setIO("input");     
        scanf("%d%d",&n,&m);
        int x,y,z;
        for(int i=1;i<=m;++i) {
            scanf("%d%d",&x,&y);
            add(x,y),add(y,x);
        }
        for(int i=1;i<=n;++i) 
            if(!vis[i]) dfs(i,0);    
        printf("NO
    ");  
        return 0; 
    }
    

      

  • 相关阅读:
    《TCP/IP详解》读书笔记
    更改vsts源代码绑定服务器地址方法
    t-sql或mssql怎么用命令行导入数据脚本
    t-sql中字符串前加N代表什么意思
    C#连接mariadb代码及方式
    sp_executesql动态执行sql语句并将结果赋值给一变量
    mariadb配置允许远程访问方式
    将DataTable转换为List,将List转换为DataTable的实现类
    SQL update select语句
    怎么区分MSSQL中nvarchar和varchar的区别?
  • 原文地址:https://www.cnblogs.com/guangheli/p/13320653.html
Copyright © 2011-2022 走看看