题目链接

https://atcoder.jp/contests/agc004/tasks/agc004_f

题解

神仙题。。

首先考虑树的情况,树是二分图,因此假设我们对二分图进行黑白染色,那么操作就变成了,每次选择两个不同色的点来取反。然后再把黑色视作标记,那么问题就变成了,初始一些点上有标记,每次可以把标记沿着边移动到一个没标记的点,要把标记全部移动到和原来不同的位置上,求最小代价!
然后这个问题的做法就是,首先如果两种颜色个数不同就无解,否则考虑一个下界,对于每一条边而言,它至少要运送标记的次数等于其一端子树内黑白点个数差的绝对值。对所有的边求和就是答案的下界,而我们也能构造出来一种达到这个下界的方案,构造详见官方题解。

然后考虑基环树。当环是奇环和偶环时,其作用不同,因此需要分类讨论。

当环是偶环时,非树边的作用是多了一条运送标记的边。假设这条边运送了\(x\)个标记(可正可负),那么其所影响的是环上的点,需要最小化的是一个\(\sum |x-a_i|\)的形式,直接取中位数即可。

当环是奇环时,非树边的作用是可以给两个端点的标记同时\(+1\)或\(-1\). 显然\(+1\)和\(-1\)都出现是不优的,由于操作可逆可以假设是\(+1\) (否则交换初始状态和终止状态)。在这种情况下,若两种颜色个数奇偶性不同就无解,否则执行这种操作的次数\(x\)是确定的(因为初始和终止时两种颜色点数确定)。那么就可以认为给这两个端点分别加了\(x\)个标记,然后再执行树的算法即可。

时间复杂度\(O(N)\)或\(O(N\log N)\).

代码

#include<bits/stdc++.h>
#define llong long long
using namespace std;const int N = 1e5;
struct Edge
{int nxt,v;
} e[(N<<1)+3];
int fe[N+3];
int fa[N+3];
bool vis[N+3];
int dep[N+3];
int a[N+3];
int s[N+3];
vector<int> vec;
int n,m,en,au,av,sum;
llong ans;int absl(int x) {return x<0?-x:x;}void addedge(int u,int v)
{en++; e[en].v = v;e[en].nxt = fe[u]; fe[u] = en;
}void dfs(int u,int prv)
{a[u] = dep[u]&1?-1:1; sum += a[u]; s[u] = a[u];vis[u] = true;for(int i=fe[u]; i; i=e[i].nxt){int v = e[i].v;if(v==prv) continue;if(vis[v]){au = u,av = v;}else{dep[v] = dep[u]+1;fa[v] = u;dfs(v,u);s[u] += s[v];}}
}void dfs2(int u,int prv)
{s[u] = a[u];vis[u] = true;for(int i=fe[u]; i; i=e[i].nxt){int v = e[i].v;if(v==prv) continue;if(vis[v]){au = u,av = v;}else{dep[v] = dep[u]+1;dfs2(v,u);s[u] += s[v];}}
}int main()
{scanf("%d%d",&n,&m);for(int i=1; i<=m; i++){int u,v; scanf("%d%d",&u,&v);addedge(u,v); addedge(v,u);}sum = 0; dep[1] = 0; dfs(1,0);if(m==n-1){if(sum) {puts("-1");}else{ans = 0ll;for(int i=1; i<=n; i++){ans += absl(s[i]);}printf("%lld\n",ans);}}else if(m==n){if(dep[au]>dep[av]) swap(au,av);if((dep[au]^dep[av])&1){if(sum) {puts("-1");}else{vec.clear();int v = av;while(dep[v]>dep[au]){vec.push_back(-s[v]);v = fa[v];}sort(vec.begin(),vec.end());int x = vec[vec.size()>>1];a[au] -= x; a[av] += x;for(int i=1; i<=n; i++) vis[i] = 0;dfs2(1,0);ans = absl(x);for(int i=1; i<=n; i++){ans += absl(s[i]);}printf("%lld\n",ans);}}else{if(absl(sum)&1) {puts("-1");}else{if(sum>0){for(int i=1; i<=n; i++) s[i] = -s[i],a[i] = -a[i];sum = -sum;}int x = (-sum)>>1;a[au] += x; a[av] += x;for(int i=1; i<=n; i++) vis[i] = 0;dfs2(1,0);ans = x;for(int i=1; i<=n; i++){ans += absl(s[i]);}printf("%lld\n",ans);}}}for(int i=1; i<=n; i++) fe[i] = vis[i] = fa[i] = 0;for(int i=1; i<=en; i++) e[i].v = e[i].nxt = 0;en = 0;return 0;
}

AtCoder AGC004F Namori (图论)相关推荐

  1. [agc004f]Namori

    前言 这题好牛逼啊. 题目大意 给你一颗全白的树或环套树. 你每次可以选择一条连接两个同色点的边,将两个端点反色. 问变成全黑的最小步数,要求判断无解. 树的做法 树是一个二分图,看起来很棒的样子. ...

  2. win10桌面图标有小白标_白标移动应用程序,带有react native和babel

    win10桌面图标有小白标 In my previous article, I described a solution for white labelling web applications wh ...

  3. AtCoder AGC043C Giant Graph (图论、SG函数、FWT)

    题目链接 https://atcoder.jp/contests/agc043/tasks/agc043_c 题解 场上感觉没啥思路就放弃了,场下想了十几分钟发现是水题,血亏...(只能怪自己计数水平 ...

  4. AtCoder AGC033F Adding Edges (图论)

    ------------恢复内容开始------------ 题目链接 https://atcoder.jp/contests/agc033/tasks/agc033_f 题解 又被神仙题搞自闭了-- ...

  5. AtCoder AGC031F Walk on Graph (图论、数论)

    题目链接 https://atcoder.jp/contests/agc031/tasks/agc031_f 题解 这题真是太神仙了-- 首先我们转化一下问题,倒着来做,一开始有一个数\(0\), 每 ...

  6. AtCoder AGC035E Develop (DP、图论、计数)

    题目链接 https://atcoder.jp/contests/agc035/tasks/agc035_e 题解 没想出来最后一步DP宛如智障-- 考虑一个数\(x\notin S\)的条件是\(x ...

  7. AtCoder AGC038D Unique Path (图论)

    题目链接 https://atcoder.jp/contests/agc038/tasks/agc038_d 题解 orz zjr神仙做法 考虑把所有\(C_i=0\)的提示的两点连边,那么连完之后的 ...

  8. AtCoder AGC022C Remainder Game (图论)

    题目链接 https://atcoder.jp/contests/agc022/tasks/agc022_c 题解 大水题一道 就他给的这个代价,猜都能猜到每个数只能用一次 仔细想想,我们肯定是按顺序 ...

  9. AtCoder AGC036D Negative Cycle (图论、DP)

    题目链接 https://atcoder.jp/contests/agc036/tasks/agc036_d 题解 这都是怎么想出来的啊..目瞪口呆系列.. 第一步转化至关重要: 一张图中不存在负环意 ...

最新文章

  1. 单链表-单链表A拆分为A(偶)和C(奇) (尾插法建表)
  2. IOS设计模式第六篇之适配器设计模式
  3. Linux环境变量配置出错,导致登录不了......
  4. linux jdk1.4 安装,linux安装jdk1.4.2
  5. java中CardLayout的使用方法
  6. MySQL事件与定时器,mysql下存储过程与定时器
  7. solidity数据位置-memory,storage和calldata
  8. Asp.net中关于上传文件的各项基本操作
  9. python在字符串结尾加反斜杠_Python原始字符串和尾部反斜杠
  10. Bailian3719 学生信息用qsort排序【排序+字符串库函数】
  11. 生命中的七堂课(转)
  12. 大型门户网站架构分析[转]
  13. SHELL下获得指定进程的进程号,并截取为整数
  14. 惠普服务器硬盘指示灯不亮或显示蓝色
  15. 脚本中fi是什么意思
  16. 产品经理与程序员之间的孽缘发展历程
  17. Tensorflow的安装与报错
  18. Intel(Altera)FPGA的SOF转JIC文件和下载详细教程
  19. vivado中ZYNQ详解(主要用于PS和PL之间的工作衔接)
  20. Linux硬盘分区mbr还是gpt,涨姿势:MBR和GPT硬盘分区表的那些事儿

热门文章

  1. 云炬Android开发笔记 4单Activity界面架构设计与验证
  2. 吴恩达《Machine Learning》精炼笔记 9:PCA 及其 Python 实现
  3. like mysql 相反_Mysql数据库的常用操作
  4. CMake1:HelloWorld
  5. PIC单片机入门_异步通讯模式详解
  6. 解决jquery的多次绑定事件
  7. 怎样写出可维护的面向对象javascript(译)
  8. python的魔法方法--__
  9. 用双向链表实现一个栈
  10. int指令---汇编学习笔记