2017国家集训队作业[agc004f]Namori

题意:

给你一颗树或环套树,树上有\(N\)个点,有\(M\)条边。一开始,树上的点都是白色,一次操作可以选择一条端点颜色相同的边,使它的端点颜色同时取反,即白色变成黑色或黑色变成白色。问,最少需要几次操作才可以把整棵树都涂成黑色?(\(N\leq10^5,N-1\le M\le N\))

题解:

参考:https://blog.csdn.net/werkeytom_ftd/article/details/78393489

我们把深度为奇数的点看做一个洞,深度为偶数的点看做有一个球,一次操作等于是把一颗球移动到相邻的空位里。那么本题就等价于把每一个球都移动到单独的一个洞里。(这就想不到了。。。)

然后这题有三种情况:

树:

根据上面的构造,树可以被看成一个二分图,那么存在可行方案当且仅当球数等于硬币数。

不妨记洞的权值为\(1\),球的权值为\(-1\),记\(v_i\)为点的权值,\(s_i\)为子树内所有权值的和。

那么最小答案就是\(\sum_{i=1}^n |s_i|\)。意义就是以\(i\)为根的子树内至少需要移进\(s_i\)个球或移出\(-s_i\)球。

奇环套树:

肯定想到的是把环上的某一条边断开,是图变成树。由于是个奇环,那么断开边上的两个端点的在新树上的深度奇偶性一定相等。那么树上的结论依然适用于这种情况。

考虑有什么不同的地方。我们发现,如果我们要操作的一开始断开的边,根据题目要求,操作之前,这两个点的颜色必须一致,我们操作这条边就等价于把这条边上的两个端点同时拿走一个球或同时放入一个球。也就是说,可行的情况变宽了,原来必须要球数和洞数相等,现在只需要球数和洞数的奇偶相等就可以。

因为让球数与洞数相等的最小操作数为\(C= \sum_{i=1}^n v_i\)

那么答案的最小可能值为\(C+\sum_{i=1}^n |s_i|\)。事实上,我们确实可以构造证明出这就是答案的最小值。(有时间再补上证明)这种情况就解决了。

偶环套树:

与奇环套树不同的是,偶环套树中环上的边断开后形成的树中,断开的边的两个端点在新树上的深度奇偶性不一样。我们没法想上一种情况一样扩宽可行条件。

但这一条边使得我们有多一种操作让球入洞,使答案变小。

假设我们在这条边上操作了\(X\)次,\(X\)为任意整数。假设这条边的两端分别为\(vs,vt\),钦定\(X\),使\(vs\) 那一端移入\(X\)个球或移出\(-X\)个球,\(vt\)那端移出\(X\)个球或移入\(-X\)个球。假设我们一开始就进行这个操作,那么这个操作只会影响包含且仅只包含\(vs\)的子树或包含且仅只包含\(vt\)的子树的权值。然后就可以用树的方法进行操作了。

记每个点的子树受\(X\)的影响为\(k_i\in\{-1,0,1\}\),最后答案就是\(|X|+\sum_{i=1}^n|k_iX+s_i|\)的最小值,取中位数即可。

呼~~~

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i,l,r) for(int i=l;i<=r;i++)
#define of(i,l,r) for(int i=l;i>=r;i--)
#define fe(i,u) for(int i=head[u];i;i=e[i].next)
using namespace std;
typedef long long ll;
inline int rd()
{
static int x,f;
x=0,f=1;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
const int N=100010;
struct edge{
int v,next;
edge(int v=0,int next=0):v(v),next(next){}
}e[N<<1];
int n,m,s[N],k[N],dep[N],q[N],vs,vt,tt;
int tot=0,head[N];
bool vis[N],flag; inline void add(int u,int v){e[++tot]=edge(v,head[u]);head[u]=tot;}
inline int fabs(int a){return a<0?-a:a;} void _dfs(int u,int fat)
{
vis[u]=1;
fe(i,u){
int v=e[i].v;
if(v==fat)continue;
if(vis[v])vs=u,vt=v,flag=(dep[v]==dep[u]);
else dep[v]=dep[u]^1,_dfs(v,u);
}
} inline bool cmp(int u,int v){return (u==vs&&v==vt)||(u==vt&&v==vs);}
void dfs(int u,int fat)
{
fe(i,u){
int v=e[i].v;
if(v==fat)continue;
if(cmp(u,v))continue;
dfs(v,u);
s[u]+=s[v];k[u]+=k[v];
}
} int main()
{
#ifndef ONLINE_JUDGE
freopen("inc.txt","r",stdin);
#endif
n=rd();m=rd();
fo(i,1,m){
int x=rd(),y=rd();
add(x,y);add(y,x);
}
dep[1]=1;flag=0;
_dfs(1,0);
int delta=0;ll ans=0;
fo(i,1,n)delta+=(s[i]=dep[i]?1:-1);
if(m==n-1){if(delta){puts("-1");return 0;}}
else{
if(flag){
if(delta&1){puts("-1");return 0;}
s[vs]-=(delta>>1),s[vt]-=(delta>>1);
ans+=abs(delta>>1);
}
else{
if(delta){puts("-1");return 0;}
k[vs]=1;k[vt]=-1;
}
}
dfs(1,0);
q[tt=1]=0;
fo(i,1,n){
if(!k[i])ans+=fabs(s[i]);
else q[++tt]=-s[i];
}
sort(q+1,q+tt+1);
int med=q[(tt+1)>>1];
fo(i,1,tt)ans+=fabs(q[i]-med);
printf("%lld\n",ans);
return 0;
}

2017国家集训队作业[agc004f]Namori的更多相关文章

  1. 2017国家集训队作业Atcoder题目试做

    2017国家集训队作业Atcoder题目试做 虽然远没有达到这个水平,但是据说Atcoder思维难度大,代码难度小,适合我这种不会打字的选手,所以试着做一做 不知道能做几题啊 在完全自己做出来的题前面 ...

  2. 2017国家集训队作业[agc016b]Color Hats

    2017国家集训队作业[agc016b]Color Hats 题意: 有\(N\)个人,每个人有一顶帽子.帽子有不同的颜色.现在,每个人都告诉你,他看到的所有其它人的帽子共有多少种颜色,问有没有符合所 ...

  3. 2017国家集训队作业[agc016e]Poor Turkey

    2017国家集训队作业[agc016e]Poor Turkey 题意: 一开始有\(N\)只鸡是活着的,有\(M\)个时刻,每个时刻有两个数\(X_i,Y_i\),表示在第\(i\)个时刻在\(X_i ...

  4. 2017国家集训队作业[agc006f]Blackout

    2017国家集训队作业[agc006f]Blackout 题意: 有一个\(N*N\)的网格,一开始有\(M\)个格子被涂黑,给出这\(M\)个格子,和染色操作:如果有坐标为\((x,y),(y,z) ...

  5. 2017国家集训队作业[arc082d]Sandglass

    2017国家集训队作业[arc082d]Sandglass 题意: ​ 有一个沙漏,初始时\(A\)瓶在上方,两个瓶子的最大容量都为\(X\)克,沙子流动的速度为\(1g\)每单位时间.给出\(K\) ...

  6. 2017国家集训队作业[arc076d/f][Exhausted?]

    2017国家集训队作业[arc076d/f][Exhausted?] 题意: ​ 有\(N\)个人,\(M\)把椅子,给出\(...L_i.R_i\)表示第\(i\)个人可以选择编号为\(1\sim ...

  7. 2017国家集训队作业[agc006e]Rotate 3x3

    2017国家集训队作业[agc006e]Rotate 3x3 题意: ​ 给你一个\(3*N\)的网格,每次操作选择一个\(3*3\)的网格,旋转\(180^\circ\).问可不可以使每个位置\(( ...

  8. 2017国家集训队作业[agc014d]Black and White Tree

    2017国家集训队作业[agc014d]Black and White Tree 题意: ​ 有一颗n个点的树,刚开始每个点都没有颜色.Alice和Bob会轮流对这棵树的一个点涂色,Alice涂白,B ...

  9. 2017国家集训队作业[agc008f]Black Radius

    2017国家集训队作业[agc008f]Black Radius 时隔4个月,经历了省赛打酱油和中考各种被吊打后,我终于回想起了我博客园的密码= = 题意: ​ 给你一棵树,树上有若干个关键点.选中某 ...

随机推荐

  1. UVa 729 The Hamming Distance Problem【枚举排列】

    题意:给出数组的长度n,给出h,表示这个数组里面含有h个1,求其所有的排列 用next_permutation就可以了 #include<iostream> #include<cst ...

  2. form表单提交的时候,传过去的值是键值对的形式

    效果展示 第一种需求,点击input的时候,input的value发生改变 $('.group-wrapper input').click(function(){ $(this).val(0); // ...

  3. Bash 基础特性

    命令别名  alias 显示当前shell中定义的所有别名  alias 别名='原始命令'  unalias 别名 取消定义的别名在命令前加\使用命令本身,而不是别名(或者使用绝对路径执行命令使用命 ...

  4. Windows 10 计划带来颜文字和Sandbox

    在最新的 Window 10 测试版 Build 18305 中,Windows 10 增加了对颜文字(kaomoji)的支持. Kaomoji 是由日本符号序列组成的面脸部表情的名称.虽然有些人,比 ...

  5. celery 学习

    1. 列出计划的ETA任务(worker) celery -A proj inspect scheduled 参考文档:http://docs.celeryproject.org/en/latest/ ...

  6. 浅析[分块]qwq

    首先说明这篇博客写得奇差无比 让我们理清一下为什么要打分块,在大部分情况下,线段树啊,splay,treap,主席树什么的都要比分块的效率高得多,但是在出问题的时候如果你和这些数据结构只是混的脸熟的话 ...

  7. hdu5336XYZ and Drops

    题意:给出r*c的网格,有的网格为空.有的有水.再给出一个爆炸点,从这个点向四周爆出四个水滴,若碰到水则融为一体,若碰到其它水滴直接跑过去互不影响.每秒可跑一格,若水中水滴数量超过4则爆开.问T秒后网 ...

  8. Find problem in eXtremeDB

    class table1 { char<8>    f1; char<80>  f2; uint4        f3; uint4        f4; double     ...

  9. java 爬虫在 netbeans 里执行和单独执行结果不一样

    在做内容測试的时候.发现我的爬虫(前些文章略有提及)在 netbeans 里面可以成功爬取网页内容,而单独执行时,给定一个 url,爬到的网页却与在浏览器里面打开 url 的网页全然不一样,这是一个非 ...

  10. shrio 加密/编码

    在涉及到密码存储问题上,应该加密/生成密码摘要存储,而不是存储明文密码.比如之前的600w csdn账号泄露对用户可能造成很大损失,因此应加密/生成不可逆的摘要方式存储. 5.1 编码/解码 Shir ...