(NC213863)牛客小白月赛29J.克隆

题意

给你n个点m条边的无向连通图。并且给你k个分身。每个分身在一个晚上只能经过 ( 2 ∗ n − k − 1 ) / k (2 * n - k - 1) / k (2nk1)/k个点,并且经过的相邻的两点之间必须有连边(这些点可以重复)。想知道存不存在一种方案使得每个点至少被一个分身经过。

思路

根据 2 ∗ n 2*n 2n和只能经过相邻的点的提示,我们想到欧拉序,在欧拉序上走必然是可以经过每个点的。

然后我们考虑分身放在哪些点。显然我们以最大步长去枚举即可,多出来的分身都走0个点就好了。

欧拉序

d f s dfs dfs序的基础上走过的点也还继续走,一笔连着走。

9 8

1 -> 2 , 1 -> 7 , 1 -> 4, 2 -> 8, 2 -> 5, 4 -> 3, 4 -> 6, 3 -> 9的图的欧拉序为:

1 2 8 2 5 2 1 7 1 4 3 9 3 4 6 4 1,和dfs序相似的,欧拉序也不唯一。

欧拉序的长度是 n + m = 2 ∗ n − 1 n + m = 2 *n - 1 n+m=2n1

#include<bits/stdc++.h>

using namespace std;

//#define int long long
const int maxn = 1e5 + 10;

vector<int>edge[maxn];
int pos[maxn << 1], tot;
bool vis[maxn];
void dfs(int u, int fa) {
    vis[u] = true;
    pos[++tot] = u;
    for(int i = 0; i < edge[u].size(); ++i) {
        int v = edge[u][i];
        if(vis[v]) continue;
        dfs(v, u);
        pos[++tot] = u;
    }
}

signed main() {
    int n, m, k; cin >> n >> m >> k;
    for (int l = 1; l <= m; ++l) {
        int u, v; cin >> u >> v;
        edge[u].push_back(v);
        edge[v].push_back(u);
    }
    dfs(1, 0);
    puts("YES");
    int step = (2 * n + k - 1) / k;
    int now = 1, i;
    for (i = 1; i <= k; ++i) {
        int next = min(now + step - 1, tot);
        int p = next - now + 1;
        printf("%d ", p);
        for (int j = 0; j < p; ++j) {
            if (j) printf(" %d", pos[now + j]);
            else printf("%d", pos[now + j]);
        }
        printf("\n");
        if (next == tot) break;
        now = next + 1;
    }
    for (++i; i <= k; ++i) puts("0");

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值