CF1586E Moment of Bloom(并查集重构树,链上结论)

19 篇文章 0 订阅
2 篇文章 0 订阅
该博客探讨了如何使用并查集处理树上的特定操作。通过分析树的结构,得出结论:去除所有奇数边的次数为树中奇数点数的一半。文章通过C++代码展示了如何构建并查集,遍历树的边来解决问题。最终,算法能够确定是否存在一种操作序列使得所有奇数节点消失,输出符合条件的路径。
摘要由CSDN通过智能技术生成

E. Moment of Bloom

分析:

  • 重构树 + + + 链上结论

    结论:若考虑在树上,去掉所有奇数边的次数为 s u m / 2 sum/2 sum/2(sum为奇数点的个数)

    对于一棵树来说,选取两个端点,这条链是唯一的

    每次操作就能去掉两个奇数点,因次 s u m sum sum 还要除以二

  • 然后用并查集在图上跑一遍生成树,再遍历每一条链即可

#include <bits/stdc++.h>
using namespace std;

const int N=1e6+5;
int f[N];
int gf(int k) { return f[k]==k ? k : f[k]=gf(f[k]); }
vector <int> g[N];
int tot,re[N];
void dfs(int u,int v,int pre)
{
    re[++tot]=u;
    if(u==v)
    {
        printf("%d\n",tot);
        for(int i=1;i<=tot;i++) printf("%d ",re[i]);
        printf("\n");
    }
    for(int to : g[u]) if(to!=pre) dfs(to,v,u);
    tot--;
}
int st[N],en[N],b[N];
signed main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) f[i]=i;
    for(int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        int x=gf(u),y=gf(v);
        if(x!=y)
        {
            f[y]=x;
            g[u].push_back(v);
            g[v].push_back(u);
        }
    }
    int q;
    scanf("%d",&q);
    for(int i=1;i<=q;i++) 
    {
        scanf("%d%d",&st[i],&en[i]);
        b[st[i]]++; b[en[i]]++;
    }
    int ans=0;
    for(int i=1;i<=n;i++) if(b[i]&1) ans++;
    if(ans) return printf("NO\n%d\n",ans/2), 0;
    puts("YES");
    for(int i=1;i<=q;i++) dfs(st[i],en[i],0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yezzz.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值