• dfs树 E. Johnny Solving


    dfs树 E. Johnny Solving

    题解:

    这个我觉得和之前写过的一个dfs树的题目有点像:

    https://www.cnblogs.com/EchoZQN/p/13394009.html

    都是dfs树,然后找环。

    贴一下我看的题解:https://blog.csdn.net/qq_40851016/article/details/101869147

    首先以1为根节点,建一棵dfs树,dfs树的性质

    每一个节点只会连向它的后代节点,或者说每一个回边都是后代连向他的祖先节点
    dfs 树构建完之后,对于一个节点,它的子节点之间是不会有边相连的。

    以1为根节点,如果到子树的最远距离是大于等于 (frac{n}{k}) 那么就直接输出第一种

    如果不是,那么就一定存在环,因为一共有n个节点,假设叶子节点的数量是 k,那么最小的最远距离是 (frac{n}{k}) ,所以说明叶子节点的数量一定大于等于k。又因为每一个点的度数一定大于等于3,那么说明一个叶子节点除了父亲节点之外,至少和两个祖先节点连了一条边,那么就构成了三个环,大小分别是:

    对于v x y (dep[v]>dep[x]>dep[y])

    s1=dep[v]-dep[x]+1 s2=dep[v]-dep[y]+1 s3=dep[x]-dep[y]+2

    容易得到:s1 s2 s3 至少有一个数不是3的倍数

    s1>=3 && s2>=3 && s3>=3

    假设 s1=3 * k1,s3 = 3 * k2

    那么可以得出 dep[x]%3=dep[y]%3

    那么s3 一定不是3的倍数

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 5e5+10;
    typedef long long ll;
    int to[maxn<<1],nxt[maxn<<1],head[maxn],cnt;
    void add(int u,int v){
        ++cnt,to[cnt]=v,nxt[cnt]=head[u],head[u]=cnt;
        ++cnt,to[cnt]=u,nxt[cnt]=head[v],head[v]=cnt;
    }
    int n,m,k,maxs=0,pos=0;
    int dep[maxn],fa[maxn],leaf[maxn];
    void dfs(int u) {
    //	printf("u=%d f=%d
    ",u,fa[u]);
        leaf[u] = 1,dep[u] = dep[fa[u]] + 1;
        if (dep[u] > maxs) maxs = dep[u],pos = u;
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (v == fa[u]) continue;
            if(dep[v]) continue;
            leaf[u] = 0;
            fa[v] = u;
            dfs(v);
        }
    }
    int main(){
        cnt = 0;
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1,u,v;i<=m;i++){
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        dfs(1);
        if(maxs>=n/k){
            printf("PATH
    %d
    ",maxs);
            while(pos){
                printf("%d ",pos);
                pos = fa[pos];
            }
        }
        else{
            printf("CYCLES
    ");
            for(int i=1;i<=n&&k;i++){
                if(!leaf[i]) continue;
                int x = 0,y = 0;
                k--;
                for(int j=head[i];j;j=nxt[j]){
                    int v = to[j];
                    if(v == fa[i]) continue;
                    if(!x) x = v;
                    else {
                        y = v;
                        break;
                    }
                }
                if(dep[x]<dep[y]) swap(x,y);
    //            printf("i=%d x=%d y=%d
    ",i,x,y);
                if((dep[i]-dep[x]+1)%3){
                    printf("%d
    ",dep[i]-dep[x]+1);
                    int u = i;
                    printf("%d ",u);
                    while(u!=x){
                        u = fa[u];
                        printf("%d ",u);
                    }
                    printf("
    ");
                }
                else if((dep[i]-dep[y]+1)%3){
                    printf("%d
    ",dep[i]-dep[y]+1);
                    int u = i;
                    printf("%d ",u);
                    while(u!=y){
                        u = fa[u];
                        printf("%d ",u);
                    }
                    printf("
    ");
                }
                else if((dep[x]-dep[y]+2)%3){
                    printf("%d
    ",dep[x]-dep[y]+2);
                    printf("%d ",i);
                    int u =x;
                    printf("%d ",u);
                    while(u!=y){
                        u = fa[u];
                        printf("%d ",u);
                    }
                    printf("
    ");
                }
            }
        }
    }
    
    
  • 相关阅读:
    201706120024 编译原理第一次作业
    P2014 选课 题解(树形DP)
    基础算法·二分答案
    P4285 [SHOI2008]汉诺塔 题解 (乱搞)
    2018.12-2019.1 TO-DO LIST
    记录一枚蒟蒻的成长(持续更新)
    P3796 【模板】AC自动机(加强版) 题解(Aho-Corasick Automation)
    BuaacodingT651 我知道你不知道圣诞节做什么 题解(逻辑)
    P2766 最长不下降子序列问题 题解(网络流)
    P2516 [HAOI2010]最长公共子序列 题解(LCS)
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/13395306.html
Copyright © 2020-2023  润新知