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\n",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\n%d\n",maxs);
while(pos){
printf("%d ",pos);
pos = fa[pos];
}
}
else{
printf("CYCLES\n");
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\n",i,x,y);
if((dep[i]-dep[x]+1)%3){
printf("%d\n",dep[i]-dep[x]+1);
int u = i;
printf("%d ",u);
while(u!=x){
u = fa[u];
printf("%d ",u);
}
printf("\n");
}
else if((dep[i]-dep[y]+1)%3){
printf("%d\n",dep[i]-dep[y]+1);
int u = i;
printf("%d ",u);
while(u!=y){
u = fa[u];
printf("%d ",u);
}
printf("\n");
}
else if((dep[x]-dep[y]+2)%3){
printf("%d\n",dep[x]-dep[y]+2);
printf("%d ",i);
int u =x;
printf("%d ",u);
while(u!=y){
u = fa[u];
printf("%d ",u);
}
printf("\n");
}
}
}
}