当前位置: 首页 > news >正文

Atcoder:AGC004F Namori

传送门
先考虑树,树是一个二分图。
看到是二分图并且每次是对两边的同色的点反色可以想到转化:让奇数层的点为黑,偶数为白,变成每次可以交换两个点的颜色。
把黑看成 \(-1\),白看成 \(1\),那么求一个子树和,考虑每一条边的贡献可以得到 \(ans=\sum_{i=1}^{n} |sum_i|\)
如果根的 \(sum\) 不为 \(0\),那么肯定是无解的。
对于基环树,先考虑奇环。
断开奇环的一条边 \((u,v)\),变成树,\(u,v\) 肯定是同一边的点。
操作一次 \((u,v)\) 相当于可以两边可以同时新增加白点/黑点,也就是可以把根的 \(sum\) 用这两个点来变成 \(0\),(\(sum\) 必须为偶数)平均分配之后用树的做法即可。
考虑偶环。
断开偶环的一条边 \((u,v)\),变成树,\(u,v\) 肯定不是同一边的点。
操作一次 \((u,v)\) 相当于是让左右的点走了一次捷径。
设用的次数为 \(x\)
如果一个点同时包含或不包含 \(u,v\) 两个点,那么 \(sum\) 一定不变。
否则加上或者减去 \(x\)
相当是是要求 \(|x|+\sum |sum_i-x| + \sum |sum_i+x|\)
经典问题,排序之后取中位数即可。

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

const int maxn(1e5 + 5);

struct Edge {  int to, next;  };

int n, m, first[maxn], cnt, sum[maxn], fa[maxn], dsu[maxn], deep[maxn], a, b, ans, val[maxn];
Edge edge[maxn << 1];

inline int Find(int x) {  return (dsu[x] ^ x) ? dsu[x] = Find(dsu[x]) : x;  }

inline void Add(int u, int v) {
    edge[cnt] = (Edge){v, first[u]}, first[u] = cnt++;
    edge[cnt] = (Edge){u, first[v]}, first[v] = cnt++;
}

void Dfs(int u, int ff, int d) {
    int e, v;
    sum[u] = d;
    for (e = first[u]; ~e; e = edge[e].next)
        if ((v = edge[e].to) ^ ff) {
            deep[v] = deep[u] + 1;
            fa[v] = u, Dfs(v, u, -d);
            sum[u] += sum[v];
        }
}

int main() {
    int i, u, v, len = 1;
    memset(first, -1, sizeof(first));
    scanf("%d%d", &n, &m);
    if (n & 1) return puts("-1"), 0;
    for (i = 1; i <= n; ++i) dsu[i] = i;
    for (i = 1; i <= m; ++i) {
        scanf("%d%d", &u, &v);
        if (Find(u) ^ Find(v)) Add(u, v), dsu[Find(u)] = Find(v);
        else a = u, b = v;
    }
    if (!a) {
        Dfs(1, 0, 1);
        if (sum[1]) return puts("-1"), 0;
    }
    else {
        Dfs(a, 0, 1);
        if (deep[b] & 1) {
            if (sum[a]) return puts("-1"), 0;
            for (i = b; i ^ a; i = fa[i]) val[++len] = sum[i], sum[i] = 0;
            sort(val + 1, val + len + 1), v = val[(len + 1) >> 1];
            for (i = 1; i <= len; ++i) ans += abs(val[i] - v);
        }
        else {
            if (sum[a] & 1) return puts("-1"), 0;
            v = sum[a] >> 1, ans = abs(v), sum[a] = 0;
            for (i = b; i ^ a; i = fa[i]) sum[i] -= v;
        }
    }
    for (i = 1; i <= n; ++i) ans += abs(sum[i]);
    printf("%d\n", ans);
    return 0;
}

转载于:https://www.cnblogs.com/cjoieryl/p/10461698.html

相关文章:

  • 如何学习JavaEE,项目又该如何做?
  • Spring Cloud构建微服务架构—服务消费(Ribbon)
  • long a = 136;
  • 使用权重正则化较少模型过拟合
  • Angular 响应式表单之下拉框
  • 基于 Babel 的 npm 包最小化设置
  • 洞悉物联网发展1000问之热点技术这么多,物联网的机会在哪里?
  • 另人的评测
  • vue 组件中solt 插槽使用
  • 设计模式(三)Animation中的策略模式
  • 手写springmvc框架
  • 你炒的肉丝为何又柴又老又难吃?
  • 刷新三观的几个网站,个个超厉害
  • 解决在V2.0中子组件使用v-model接收来自父组件的值异常
  • 商城系统 DBShop V1.3 Release 20190309 发布
  • 时间复杂度分析经典问题——最大子序列和
  • 【笔记】你不知道的JS读书笔记——Promise
  • 【跃迁之路】【669天】程序员高效学习方法论探索系列(实验阶段426-2018.12.13)...
  • CentOS从零开始部署Nodejs项目
  • Facebook AccountKit 接入的坑点
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • Laravel 中的一个后期静态绑定
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • scrapy学习之路4(itemloder的使用)
  • springboot_database项目介绍
  • UEditor初始化失败(实例已存在,但视图未渲染出来,单页化)
  • Vue组件定义
  • Webpack 4 学习01(基础配置)
  • 从零开始的无人驾驶 1
  • 电商搜索引擎的架构设计和性能优化
  • 对象管理器(defineProperty)学习笔记
  • 高程读书笔记 第六章 面向对象程序设计
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 容器服务kubernetes弹性伸缩高级用法
  • 世界上最简单的无等待算法(getAndIncrement)
  • 学习笔记:对象,原型和继承(1)
  • 不要一棍子打翻所有黑盒模型,其实可以让它们发挥作用 ...
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • #pragam once 和 #ifndef 预编译头
  • (003)SlickEdit Unity的补全
  • (2020)Java后端开发----(面试题和笔试题)
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (三)elasticsearch 源码之启动流程分析
  • (四)图像的%2线性拉伸
  • (转)编辑寄语:因为爱心,所以美丽
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .net web项目 调用webService
  • .net连接oracle数据库
  • @cacheable 是否缓存成功_让我们来学习学习SpringCache分布式缓存,为什么用?
  • @WebServiceClient注解,wsdlLocation 可配置
  • [202209]mysql8.0 双主集群搭建 亲测可用
  • [Android Studio 权威教程]断点调试和高级调试
  • [AR]Vumark(下一代条形码)
  • [C#][opencvsharp]opencvsharp sift和surf特征点匹配