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("
");
            }
        }
    }
}

原文地址:https://www.cnblogs.com/EchoZQN/p/13395306.html