正解:
解题报告:
首先看数据范围可以发现要么是棵树要么是个奇环要么是个偶环
然后就分类讨论分别看下这几个情况
首先是棵树的
首先可以想到树的情况就是个二分图,所以不妨把颜色重定义,让奇数层的变成白色偶数层的变成黑色,然后就变成了,可以交换一个黑色和一个白色,求能否让白的都变成黑的.黑的都变成白的
然后再赋个值,令黑色为-1白色为1
首先无解的情况很容易想到嘛,就是当黑色白色的点本来就不相等的时候显然是布星的
然后继续想,设f[i]:点i额外转换的次数
显然答案的下界是∑abs(f[i])
然后可以想到这个∑abs(f[i])显然是可以达到的,有点儿像一个贪心的基础题忘了叫什么了,,,反正挺显然的?
然后考虑有环的情况,这儿要分奇环偶环分开讨论下
对于奇环,就相当于是连了同一奇偶性的两个点,就是说本来正常交换是一个+1一个-1正好抵消,而这样做就变成了都+1或者都+2,那就可以不保证黑色白色相等了,只要黑色白色的差值是偶数就可以通过这条边抵消掉
所以可以发现这条边的用处就是抵消差值,所以可以先算出差值,然后as+=差值/2,这时候这条边的作用就用完了,剩下就当树一样处理就好
对于偶环,其实从大局来看就和树是差不多的,就是假如现在已经在它们的lca之上了,那么这条多余的链反正修改起来也是+1-1的所以麻油什么影响
所以可以发现有影响的只是lca的子树内部的,也就是那个环上的
可以考虑设这条多余的链上运输了x次,然后可以发现,会改变的就左端点到lca会+=x,右端点到lca会-=x
然后被修改了的值列成式子就会变成,∑abs(t*f[i]-x),然后这儿t是±1,能get趴?就上面那个式子嘛
然后这个式子再仔细一看,小学奥数鸭,绝对值之和min就是取中位数的时候嘛
然后就做完啦啦啦!
放下代码QAQ
![](https://i-blog.csdnimg.cn/blog_migrate/a2b7024cb6a8cccd23244148c90016f0.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/aa7790439652fcf252898472b6dc57b7.gif)
#include<bits/stdc++.h> using namespace std; #define il inline #define ll long long #define rg register #define gc getchar() #define t(i) edge[i].to #define rp(i,x,y) for(rg int i=x;i<=y;++i) #define my(i,x,y) for(rg int i=x;i>=y;--i) #define e(i,x) for(rg int i=head[x];i;i=edge[i].nxt) const int N=1e5+10; int n,m,head[N],ed_cnt,sz[N],st,to,sum,as,top,stck[N],g[N]; struct ed{int to,nxt;}edge[N<<1]; bool jud; bool vis[N]; il int read() { rg char ch=gc;rg int x=0;rg bool y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } il void ad(int x,int y){edge[++ed_cnt]=(ed){x,head[y]};head[y]=ed_cnt;} void dfs1(int x,int fa){e(i,x)if(t(i)^fa)if(sz[t(i)]){if(sz[t(i)]==sz[x])jud=1;st=x;to=t(i);}else sz[t(i)]=-sz[x],dfs1(t(i),x);} void dfs2(int x,int fa){vis[x]=1;e(i,x)if(t(i)^fa && !((x==st && t(i)==to) || (x==to && t(i)==st)))dfs2(t(i),x),sz[x]+=sz[t(i)],g[x]+=g[t(i)];return;} int main() { n=read();m=read();rp(i,1,m){int x=read(),y=read();ad(x,y);ad(y,x);}sz[1]=1;dfs1(1,0); rp(i,1,n)sum+=sz[i];if(!jud)if(sum)return printf("-1\n"),0; if(m==n)if(jud){if(sum&1)return printf("-1\n"),0;as+=abs(sum>>1);sz[st]-=(sum>>1);sz[to]-=(sum>>1);}else g[st]=1,g[to]=-1; dfs2(1,0); rp(i,1,n){if(g[i])stck[++top]=g[i]*sz[i];else as+=abs(sz[i]);} stck[++top]=0;sort(stck+1,stck+top+1);int mid=stck[(top+1)>>1]; rp(i,1,top)as+=abs(stck[i]-mid); printf("%lld\n",as); return 0; }