zoukankan      html  css  js  c++  java
  • LOJ #6042. 「雅礼集训 2017 Day7」跳蚤王国的宰相

    我可以大喊一声这就是个思博题吗?

    首先如果你能快速把握题目的意思后,就会发现题目就是让你求出每个点要成为树的重心至少要嫁接多少边

    先说一个显然的结论,重心的答案为(0)(废话)

    然后我们考虑贪心处理,每次肯定要砍断以重心为根的树的大小尽量大的子树

    那么至少要砍多少呢,至少(frac{1}{2})要到吧,然后就是思博的感性理解了——这是每个点要砍的边的上界

    假如我们总有一种方案可以使嫁接满足条件(兴许更多,但是这个不会证啊)

    那么怎么判断是否达到上界呢,很简单,先取了必要的然后看剩下的有没有超过(frac{1}{2})即可

    这个文字不好表述,大家还是自己看看代码吧

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #define RI register int
    #define CI const int&
    #define Tp template <typename T>
    using namespace std;
    const int N=1000005;
    struct edge
    {
    	int to,nxt;
    }e[N<<1]; int n,head[N],x,y,cnt,rt,mx[N],size[N],rch[N],tot,sum,cur,ans[N];
    class FileInputOutput
    {
    	private:
    		static const int S=1<<21;
    		#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
    		#define pc(ch) (Ftop<S?Fout[Ftop++]=ch:(fwrite(Fout,1,S,stdout),Fout[(Ftop=0)++]=ch))
    		char Fin[S],Fout[S],*A,*B; int Ftop,pt[15];
    	public:
    		Tp inline void read(T& x)
    		{
    			x=0; char ch; while (!isdigit(ch=tc()));
    			while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
    		}
    		Tp inline void write(T x)
    		{
    			if (!x) return (void)(pc('0'),pc('
    ')); RI ptop=0;
    			while (x) pt[++ptop]=x%10,x/=10; while (ptop) pc(pt[ptop--]+48); pc('
    ');
    		}
    		inline void Fend(void)
    		{
    			fwrite(Fout,1,Ftop,stdout);
    		}
    		#undef tc
    		#undef pc
    }F;
    inline void addedge(CI x,CI y)
    {
    	e[++cnt]=(edge){y,head[x]}; head[x]=cnt;
    	e[++cnt]=(edge){x,head[y]}; head[y]=cnt;
    }
    inline int max(CI a,CI b)
    {
    	return a>b?a:b;
    }
    inline bool cmp(CI x,CI y)
    {
    	return size[x]>size[y];
    }
    #define to e[i].to
    inline void getrt(CI now,CI fa=0)
    {
    	size[now]=1; for (RI i=head[now];i;i=e[i].nxt) if (to!=fa)
    	getrt(to,now),size[now]+=size[to],mx[now]=max(mx[now],size[to]);
    	if (mx[now]=max(mx[now],n-size[now]),mx[now]<mx[rt]) rt=now;
    }
    inline void DFS(CI now,CI fa=0)
    {
    	size[now]=1; for (RI i=head[now];i;i=e[i].nxt)
    	if (to!=fa) DFS(to,now),size[now]+=size[to];
    }
    inline void calc(CI now,CI fa,CI used)
    {
    	ans[now]=cur+((n-used-size[now]<<1)>n?0:-1);
    	for (RI i=head[now];i;i=e[i].nxt) if (to!=fa) calc(to,now,used);
    }
    int main()
    {
    	//freopen("B.in","r",stdin); freopen("B.out","w",stdout);
    	RI i; for (F.read(n),i=1;i<n;++i) F.read(x),F.read(y),addedge(x,y);
    	for (mx[rt]=1e9,getrt(1),i=head[rt];i;i=e[i].nxt) rch[++tot]=to;
    	for (DFS(rt),sort(rch+1,rch+tot+1,cmp),i=1;i<=tot;++i)
    	if (((sum+=size[rch[i]])<<1)>=n) { cur=i; break; }
    	for (i=1;i<=tot;++i) calc(rch[i],rt,sum-max(size[rch[i]],size[rch[cur]]));
    	for (i=1;i<=n;++i) F.write(ans[i]); return F.Fend(),0;
    }
    
  • 相关阅读:
    【雕爷学编程】MicroPython动手做(01)——春节后入手了K210开发板
    【雕爷学编程】零基础Python(01)---“投机取巧”的三条途径
    【雕爷学编程】Arduino动手做(64)---RGB全彩LED模块
    Microsoft Development Platform Technologies
    JS 的Date对象
    SQL数据库连接池与C#关键字return
    RDLC报表 报表数据 栏 快捷键
    C# 操作World生成报告
    SAP-ABAP系列 第二篇SAP ABAP开发基础
    SAP-ABAP系列 第一篇SAP简介
  • 原文地址:https://www.cnblogs.com/cjjsb/p/10673266.html
Copyright © 2011-2022 走看看