ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1103C Johnny Solving(构造题)

2021-09-22 23:03:28  阅读:157  来源: 互联网

标签:leaf Johnny dep ed Solving CF1103C int printf include


洛谷传送门


解题思路

在图上很难做这种构造题,所以一种常用的方法是求出其生成树

生成树上做就容易很多。

于是这个题就按照 dfs 序建立一颗生成树,记录下每个节点的返祖边。

于是第一问可以根据树的深度判断是否符合要求,符合的话直接输出。

若没有,则易证第二问一定成立:

因为第一问不成立,所以叶子节点数一定 \(\geqslant k\),而题中保证每个节点的度数 \(\geqslant3\),也就暗示了叶子节点都有 \(\geqslant2\) 条返祖边。

所以一定能从每个叶子节点找到一个符合要求的环。

假设叶子节点 k 的两个返祖祖先为 x 和 y,则通过作差法易证:

\((dep[u]-dep[x]+1)\) 和 \((dep[u]-dep[y]+1)\) 和 \((dep[y]-dep[x]+2)\) 中至少有一个不是 \(3\) 的倍数。

判断一下输出即可。

注意

数组一定要开够:大小为 m 的两倍!否则会在第四个点TLE。

AC代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=5e5+5;
int n,m,k,cnt,cnt_leaf,leaf[maxn],p[maxn],dep[maxn],fa[maxn],ancestor[maxn][105];
int maxdep,ed;
template <typename T>
inline void read(T &x)
{
    char c;
    x=0;
    int fu=1;
    c=getchar();
    while(c>57||c<48){
        if(c==45){
        	fu=-1;
        }
        c=getchar();
    }
    while(c<=57&&c>=48)
    {
        x=(x<<3)+(x<<1)+c-48;
        c=getchar();
    }
    x*=fu;
}
struct node{
	int v,next;
}e[maxn*2];
void insert(int u,int v){
	cnt++;
	e[cnt].v=v;
	e[cnt].next=p[u];
	p[u]=cnt;
}
void dfs(int u,int f,int deep){
	dep[u]=deep;
	if(dep[u]>maxdep){
		maxdep=dep[u];
		ed=u;
	}
	fa[u]=f;
	leaf[++cnt_leaf]=u;
	for(int i=p[u];i!=-1;i=e[i].next){
		int v=e[i].v;
		if(v==f) continue;
		if(dep[v]){
			ancestor[u][++ancestor[u][0]%100]=v;
			continue;
		}
		if(leaf[cnt_leaf]==u) cnt_leaf--;
		dfs(v,u,deep+1);
	}
}
void print(int u,int to){
	printf("%d ",to);
	if(u==to) return;
	print(u,fa[to]);
}
int main(){
	memset(p,-1,sizeof(p));
	read(n);
	read(m);
	read(k);
	for(int i=1;i<=m;i++){
		int u,v;
		read(u);
		read(v);
		insert(u,v);
		insert(v,u);
	} 
	dfs(1,-1,1);
	if(maxdep>=(n-1)/k+1){
		puts("PATH");
		printf("%d\n",maxdep);
		while(ed!=-1){
			printf("%d ",ed);
			ed=fa[ed];
		}
		return 0;
	}
	puts("CYCLES");
	for(int i=1;i<=k;i++){
		int u=leaf[i],x=ancestor[u][1],y=ancestor[u][2];
		if(dep[x]>dep[y]) swap(x,y);
		if((dep[u]-dep[x]+1)%3!=0){
			printf("%d\n",dep[u]-dep[x]+1);
			print(x,u);
			puts("");
		}else{
			if((dep[u]-dep[y]+1)%3!=0){
				printf("%d\n",dep[u]-dep[y]+1);
				print(y,u);
				puts("");
			}else{
				printf("%d\n%d ",dep[y]-dep[x]+2,u);
				print(x,y);
				puts("");
			}
		}
	}
    return 0;
}

标签:leaf,Johnny,dep,ed,Solving,CF1103C,int,printf,include
来源: https://www.cnblogs.com/yinyuqin/p/15321926.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有