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\n",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\n",res);
            while(x!=y){
                printf("%d ",x);x=fa[x];
            }
            printf("%d\n",y);continue;
        }
        res=d[x]-d[z]+1;
        if(res%3){
            printf("%d\n",res);
            while(x!=z){
                printf("%d ",x);x=fa[x];
            }
            printf("%d\n",z);continue;
        }
        if(d[y]<d[z])swap(y,z);
        res=d[y]-d[z]+2;
        printf("%d\n",res);
        while(y!=z){
            printf("%d ",y);y=fa[y];
        }
        printf("%d %d\n",z,x);
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Jessie-/p/10534332.html