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. ELK到底是什么?那么多公司用!__转载

    Sina.饿了么.携程.华为.美团.freewheel.畅捷通 .新浪微博.大讲台.魅族.IBM...... 这些公司都在使用ELK!ELK!ELK! ELK竟然重复了三遍,是个什么?   一.ELK ...

  2. mac terminal终端怎么退出python命令行

    >>>使用 quit(), exit(), 或者Command+d,或者Command+z退出命令行.

  3. 01背包-第k优解

    The title of this problem is familiar,isn't it?yeah,if you had took part in the "Rookie Cup&quo ...

  4. 今日SGU 5.27

    SGU 122 题意:给你n个人,每个人有大于 N / 2(向上取整)的朋友,问你1这个人有一个书,每个人都想看,只能从朋友之间传递,然后最后回到了1这个人,问你 是否有解,然后有解输出路径 收获:哈 ...

  5. ECNUOJ 2856 仰望星空

    仰望星空 Time Limit:1000MS Memory Limit:65536KBTotal Submit:373 Accepted:145 Description  我仰望星空, 它是那样辽阔而 ...

  6. scala细节

    在高版本中,scala使用了自己的String,而不是java.lang.String 字符串转数字:"33.4".toDouble    "33.4".toF ...

  7. 关于App程序猿泡沫

    前言 做开发快七年了,对于程序猿,外行人总有着数不完的讽刺和误解,可是我都懒得去解释.代码搬运工人也好,民工也罢,随他们去说吧.可是网上近期流传的程序猿泡沫,尤其是APP程序猿泡沫的文章导致非常多我们 ...

  8. PostgreSQL数据库创建/删除

    方法1 - 系统命令 sudo su - postgres #切换到postgres用户(系统用户) createdb weichen #创建数据库 psql #直接訪问数据库(默认进入本地postg ...

  9. 美团实习生电面之谈(成功拿到offer)

    3月底进行了美团的一次实习生面试(Java研发project师).当时顺利的通过一面.以下是我的一面: 1.CPU由哪些部分组成 2.线程和进程的差别 3.Java类载入机制 4.怎样实现一个字符串的 ...

  10. Linux 6.2配置yum本地

    yum 1.挂在iso文件 [root@localhostmedia]# mount /dev/cdrom /media 2.安装createrepo createrepo是配置YUM源的配置工具,检 ...