• CF1103C Johnny Solving


    题目大意:

    给出一张无重边的无向图(保证每个点度数大于等于 $3$ )和一个限制 $k$ ,需要你构造以下两种情况中的一种:

    1. 找出一条路径长度为 $frac{n}{k}$ 。

    2. 找出 $k$ 个环,使得每个环的长度大于 $3$ 而且不是 $3$ 的倍数,并且要求保证每个环中至少有一个点在这 $k$ 个环里只出现一次。

    思路:

    考虑先建出一棵 $dfs$ 树,这时对于这棵树如果最长链长度大于 $frac{n}{k}$ 那么就直接输出这条链,否则意味着每条链深度都小于 $frac{n}{k}$ 。

    那么这棵树至少有 $k$ 个叶子节点。

    因为每一个节点度数大于等于 $3$ ,所以至少会有两条返祖边向上,假设连向 $a,b$ 两个节点,如果叶子节点分别和 $a,b$ 构成的环都恰好是 $3$ 的倍数,那么 $a,b$ 之间的链连上叶子节点构成的环就必然不为 $3$ 的倍数。这样对于 $geq k$ 个叶子节点都能找到一个合法的环,输出任意 $k$ 个即可。

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=3e5+5,M=5e5+5;
    bool vis[N];
    int q[N],tot,fa[N];
    int n,m,k,head[N],ne[M<<1],to[M<<1],cnt,d[N];
    il int read(){
       int x,f=1;char ch;
       _(!)ch=='-'?f=-1:f;x=ch^48;
       _()x=(x<<1)+(x<<3)+(ch^48);
       return f*x;
    }
    il void ins(int x,int y){
        ne[++cnt]=head[x];
        head[x]=cnt;to[cnt]=y;
    }
    il void dfs(int x){
        vis[x]=1;
        if(d[x]>=(n+k-1)/k){
            puts("PATH");printf("%d
    ",d[x]);
            while(x)printf("%d ",x),x=fa[x];
            exit(0);
        }
        bool pd=0;
        for(int i=head[x];i;i=ne[i]){
            if(fa[x]==to[i]||vis[to[i]])continue;
            fa[to[i]]=x;d[to[i]]=d[x]+1;pd=1;
            dfs(to[i]);
        }
        if(!pd)q[++tot]=x;
    }
    int main()
    {
        n=read();m=read();k=read();
        for(int i=1;i<=m;i++){
            int x=read(),y=read();
            ins(x,y);ins(y,x);
        }
        d[1]=1;dfs(1);
        puts("CYCLES");
        for(int j=1;j<=k;j++){
            int x=q[j],y=0,z=0;
            for(int i=head[x];i;i=ne[i]){
                if(fa[x]==to[i])continue;
                if(!y)y=to[i];else z=to[i];
            }
            int res=d[x]-d[y]+1;
            if(res%3){
                printf("%d
    ",res);
                while(x!=y){
                    printf("%d ",x);x=fa[x];
                }
                printf("%d
    ",y);continue;
            }
            res=d[x]-d[z]+1;
            if(res%3){
                printf("%d
    ",res);
                while(x!=z){
                    printf("%d ",x);x=fa[x];
                }
                printf("%d
    ",z);continue;
            }
            if(d[y]<d[z])swap(y,z);
            res=d[y]-d[z]+2;
            printf("%d
    ",res);
            while(y!=z){
                printf("%d ",y);y=fa[y];
            }
            printf("%d %d
    ",z,x);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    linux上修改系统默认语言设置
    【计算机基础之编程语言】编程语言的发展
    【Java语言特性学习之四】常用集合
    【Java语言特性学习之三】Java4种对象引用
    【Java语言特性学习之二】反射
    【网络知识之七】QUIC(http3)
    【网络知识之六】UDP
    【网络知识之五】TCP
    【网络知识之四】HTTP/2
    【网络知识之三】HTTPS协议
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10534332.html
Copyright © 2020-2023  润新知