在花园里劳累了一上午以后,你决定用本身种的干辣椒奖励本身。
你有n个辣椒,这些辣椒用n-1条绳子链接在一块儿,任意两个辣椒经过用若干个绳子相连,即造成一棵树。
你决定分三餐吃完这些辣椒,所以须要剪断其中两根绳子,从而获得三个组成部分,每一餐吃一个组成部分便可。
每一餐不能够太辣,因此你会寻找一个剪绳子的方法,使得最大组成部分和最小组成部分的辣椒数量差最小。计算出这个最小差值。node
输入文件名为chilli.in。
第一行一个整数n,表示辣椒的数量。辣椒从1到n进行编号。
下面n-1行每一行包含两个整数x和y(1≤x,y≤n),表示辣椒x和辣椒y直接用一根绳子相连。ios
输出文件名为chilli.out。
输出最小差值。spa
题目大意:删掉一棵树上的两条边使得造成的三棵树里\(size\)最大的减\(size\)最小的差值最小,问最小差值
先求出以每一个点为根的子树的大小\(size_i\)(假定1为整棵树的根)
而后枚举每一个点(用\(dfs\),在到每一个点的时候就计算贡献,即删除当前点与父亲的边,作完以后把\(n-size_x\)加到\(set\),结束后从\(set\)中移除),删掉它与它父亲的边,这时将整棵树分红两部分:\(size_x\)和\(n-size_x\),而后在\(n-size_x\)里找到\(\lceil\dfrac{n-size_x}{2}\rceil\)的前驱后继,这里能够用\(set\)里的\(lower\_bound\)(不会用\(set\)能够自行搜索,这里推荐一篇写的比较好的文章https://blog.csdn.net/qq_34243930/article/details/81481929)。关于另外一条边,有两种状况,一种是祖先边,上面已经计算,另外一种是非祖先边,能够再用一个\(dfs\),但与上面有所不一样,这里是删除当前点与儿子的边,而后结束后加入\(size_x\).net
#include<set> #include<cstdio> #include<cstring> #include<iostream> #define inf 2147483600 using namespace std; struct node { int next,to,head; }a[400001]; int n,x,y,ans,tot,size[200001]; multiset<int> q; multiset<int>::iterator it; void add(int x,int y) { a[++tot].to=y; a[tot].next=a[x].head; a[x].head=tot; } void getsize(int now,int fa) { size[now]=1; for (int i=a[now].head;i;i=a[i].next) { if (a[i].to==fa) continue; getsize(a[i].to,now); size[now]+=size[a[i].to]; } } int getans(int x,int y,int z) {return max(x,max(y,z))-min(x,min(y,z));} void calc(int x) { int p=n-size[x]; it=q.lower_bound((p+1)>>1); if (it!=q.end()) ans=min(ans,getans(size[x],p-*it,*it)); if (it!=q.begin()) it--,ans=min(ans,getans(size[x],p-*it,*it)); it=q.lower_bound(max(size[x],p-size[x])); if (it!=q.end()) ans=min(ans,*it*2-p); } void dfs1(int now,int fa) { calc(now); q.insert(n-size[now]); for (int i=a[now].head;i;i=a[i].next) { if (a[i].to==fa) continue; dfs1(a[i].to,now); } q.erase(n-size[now]); } void dfs2(int now,int fa) { for (int i=a[now].head;i;i=a[i].next) { if (a[i].to==fa) continue; calc(a[i].to); dfs2(a[i].to,now); } q.insert(size[now]); } int main() { freopen("chilli.in","r",stdin); freopen("chilli.out","w",stdout); scanf("%d",&n); for (int i=1;i<n;++i) { scanf("%d%d",&x,&y); add(x,y);add(y,x); } ans=inf; getsize(1,0); dfs1(1,0); dfs2(1,0); printf("%d\n",ans); fclose(stdin); fclose(stdout); return 0; }