Johnny Solving CodeForces - 1103C (构造,图论)

大意: 无向图, 无重边自环, 每个点度数>=3, 要求完成下面任意一个任务

  • 找一条结点数不少于n/k的简单路径
  • 找k个简单环, 每个环结点数小于n/k, 且不为3的倍数, 且每个环有一个特殊点$x$, $x$只属于这一个环

任选一棵生成树, 若高度>=n/k, 直接完成任务1, 否则对于叶子数一定不少于k, 而叶子反向边数>=2, 一定可以构造出一个环

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <string.h>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define hr putchar(10)
#define pb push_back
#define lc (o<<1)
#define rc (lc|1)
#define mid ((l+r)>>1)
#define ls lc,l,mid
#define rs rc,mid+1,r
#define x first
#define y second
#define io std::ios::sync_with_stdio(false)
#define endl ‘\n‘
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int P = 1e9+7, INF = 0x3f3f3f3f;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;}
ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;}
//head

const int N = 1e6+10;
int n, m, k;
vector<int> g[N];
int q[N];
int dep[N], vis[N], fa[N];

void dfs(int x, int f, int d) {
	vis[x]=1,fa[x]=f,dep[x]=d;
	if (d>=(n+k-1)/k) {
		puts("PATH");
		printf("%d\n", d);
		while (x) printf("%d ",x),x=fa[x];
		puts(""),exit(0);
	}
	int ok = 0;
	for (int y:g[x]) if (!vis[y]) {
		ok = 1, dfs(y,x,d+1);
	}
	if (!ok) q[++*q]=x;
}

int main() {
	scanf("%d%d%d", &n, &m, &k);
	REP(i,1,m) {
		int u, v;
		scanf("%d%d", &u, &v);
		g[u].pb(v),g[v].pb(u);
	}
	dfs(1,0,1);
	puts("CYCLES");
	REP(i,1,k) {
		int x=0, y=0, z=q[i];
		for (int t:g[z]) if (t!=fa[z]) {
			if (!x) x=t;
			else y=t;
		}
		if ((dep[z]-dep[x]+1)%3) {
			printf("%d\n",dep[z]-dep[x]+1);
			for (; printf("%d ",z), z!=x; z=fa[z]) ;
		} else if ((dep[z]-dep[y]+1)%3) {
			printf("%d\n",dep[z]-dep[y]+1);
			for (; printf("%d ",z), z!=y; z=fa[z]) ;
		} else {
			if (dep[x]<dep[y]) swap(x,y);
			printf("%d\n", dep[x]-dep[y]+2);
			for (; printf("%d ",x), x!=y; x=fa[x]) ;
			printf("%d", z);
		}
		puts("");
	}
}

原文地址:https://www.cnblogs.com/uid001/p/10500245.html

时间: 2024-08-30 14:59:59

Johnny Solving CodeForces - 1103C (构造,图论)的相关文章

CF1103C Johnny Solving (Codeforces Round #534 (Div. 1)) 思维+构造

题目传送门 https://codeforces.com/contest/1103/problem/C 题解 这个题还算一个有难度的不错的题目吧. 题目给出了两种回答方式: 找出一条长度 \(\geq \frac nk\) 的路径: 找出 \(k\) 个简单环,满足长度不是 \(3\) 的倍数,并且每个环至少存在一个点不在别的环中. 很显然题目并不是要你随便挑一种回答方式开始单独研究.最有可能的情况是两种回答方式可以替补. 如果我们随便作出原图的一棵生成树,如果最长的路径长度 \(\geq \f

CCO2017 Vera and Trail Building 构造+图论

正解:构造+图论 解题报告: 这题好像只有这儿有QwQ 这题好像麻油翻译,,,我先翻译下QAQ 一个图上,如果存在(a,b)满足a<b且存在从a到b再回到a的路径,每条道路被经过至多一次,我们称(a,b)为完美点对试构造一个点数和边数不超过5000的无向连通图,其完美点对数量恰好为K k<=107 昂这题也比较简单啊,,,就每次都尽量大地构边双联通分量 然后把他们连起来就好辣 显然连起来是不会构造完美点对的 然后关于边双联通分量,可以得到当有n个点的时候完美点对的数量为n(n-1)/2 然后就

CodeForces 1103C. Johnny Solving

题目简述:给定简单(无自环.无重边)连通无向图$G = (V, E), 1 \leq n = |V| \leq 2.5 \times 10^5, 1 \leq m = |E| \leq 5 \times 10^5$,保证任意节点的度数$\geq 3$.给定参数$1 \leq k \leq n$,要求完成以下任务之一: 1. 找到一条包含至少$\frac n k$个节点的简单路径. 2. 找到$k$个简单环,使得 2.1. 每个环包含少于$\frac n k$个节点,且包含的节点个数不得被$3$整

B - Save the problem! CodeForces - 867B 构造题

B - Save the problem! CodeForces - 867B 这个题目还是很简单的,很明显是一个构造题,但是早训的时候脑子有点糊涂,想到了用1 2 来构造, 但是去算这个数的时候算错了... 用1 2 来构造 可以先枚举一些数来找找规律. 1 1 2 2 3 1 1 1    2 1 1 4 .... 可以发现每一个数都是 n/2+1 的可能, 所以反过来推过去就是 (s-1)*2  或者(s-1)*2+1 这个(s-1)*2+1的答案才是正确答案 因为 这个s可以==1 #i

Codeforces 1188A 构造

题意:给你一颗树,树的边权都是偶数,并且边权各不相同.你可以选择树的两个叶子结点,并且把两个叶子结点之间的路径加上一个值(可以为负数),问是否可以通过这种操作构造出这颗树?如果可以,输出构造方案.初始树的边权都是0. 思路:A1很简单,只要判断是否有度数为2的点就可以了.对于A2, 由于边权各不相同,所以A1的结论同样适用.现在我们来构造一组答案.官方题解的构造方式是这样的:我们假设要让一个节点u到叶子结点v的路径都加上一个值x,并且知道叶子结点l1, l2都可以到达u,我们执行以下操作:v到l

Codeforces 22E(图论)

题意: 给出n个节点,以及和这个节点指向的节点fi,表示从i能够到达fi,问至少需要添加多少条边能够使得原图变为强连通分量, 输出边数及添加的边,多解输出任意一组解. 2 <= n <= 1e5, 1 <= fi <= n && i != fi. 分析: 注意隐含条件,每个点只有一条出边 所以对于每个连通分量来说,一定是一个有向环上挂着几个有向树 如果只有一个连通分量,那么直接从环上任意一点去连所有的入度为0的点即可 但现在有多个连通分量,先要把连成一个连通分量 我

The minimal unique substring CodeForces - 1159D (构造)

核心观察是形如01,001,0001,...的串循环时, $n$每增长1, $k$就增长1. #include <iostream> #include <sstream> #include <algorithm> #include <cstdio> #include <math.h> #include <set> #include <map> #include <queue> #include <stri

Codeforces Round #534 (Div. 2)题解

Codeforces Round #534 (Div. 2)题解 A. Splitting into digits 题目大意 将一个数字分成几部分,几部分求和既是原数,问如何分可以使得分出来的各个数之间的差值尽可能小 解题思路 将n分成n个1相加即可 AC代码 #include<cstring> #include<string> #include<iostream> #include<cstdio> using namespace std; int main

Codeforces Round #534 (Div. 2)

A. Splitting into digits 题意:把一个数分成若干[1,9]之间的数字,使得这些数尽量相同. 思路:输出n个1. #include<bits/stdc++.h> #define CLR(a,b) memset(a,,sizeof(a)) using namespace std; typedef long long ll; const int maxn=100010; int main(){ int n; cin>>n; int flag=0,j=2; prin