zoukankan      html  css  js  c++  java
  • CF1442E. Black, White and Grey Tree

    题目大意

    一棵黑白灰的树,每次选择一个连通块内的一个子点集将其删掉,不能同时删黑白点,求最少删完的次数

    n<=2e5

    题解

    不是这DE加起来怎么还没有C难写啊

    发现把树删成两个连通块不比从外往内删优,因为可以同时删更多的点

    又发现灰色点一定不会先删,一定是相邻的点只剩一个时跟着那个点一起删

    转化一下,先把灰色块缩成一个点,之后把其相连的黑白点缩成两个点,最后删掉灰色点并把合成的黑白两个点连起来,如果只有某一种颜色就不用连,这样得到的图和原图等价

    因为一个灰色点被删的时间是与其相连的点的最晚被删时间,所以缩起来之后时间并没有变

    接着再把黑色和白色块缩起来,变成一棵黑白交替的树,那么此时再从叶子一层层往内删,答案就是直径/2+1

    然后在U群里看到说直接找直径就可以了,原理等价于普通树找直径,证明用反证法把端点移到直径端点上

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define ll long long
    //#define file
    using namespace std;
    
    int a[400001][2],b[200001],ls[200001],T,n,i,j,k,l,len,mx,mx2;
    
    void New(int x,int y) {++len;a[len][0]=y;a[len][1]=ls[x];ls[x]=len;}
    void dfs(int Fa,int t,int Ls,int sum)
    {
    	int i;
    	if (sum>mx) mx=sum,mx2=t;
    	
    	for (i=ls[t]; i; i=a[i][1])
    	if (a[i][0]!=Fa)
    	dfs(t,a[i][0],(b[a[i][0]]>0)?b[a[i][0]]:Ls,sum+(b[a[i][0]]>0 && b[a[i][0]]!=Ls));
    }
    
    int main()
    {
    	#ifdef file
    	freopen("CF1442E.in","r",stdin);
    	#endif
    	
    	scanf("%d",&T);
    	for (;T;--T)
    	{
    		scanf("%d",&n),len=0,memset(ls,0,(n+1)*4);
    		fo(i,1,n) scanf("%d",&b[i]);
    		fo(i,1,n-1) scanf("%d%d",&j,&k),New(j,k),New(k,j);
    		
    		mx=-1,dfs(0,1,b[1],b[1]>0);
    		mx=-1,dfs(0,mx2,b[mx2],b[mx2]>0);
    		printf("%d
    ",mx/2+1);
    	}
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    SqlServer事务日志满的解决方案
    关于.net反射和metadata加载致Jeffray Zhao等几位和firelong
    Context Root选/的原则
    [继续讨论]关于Windows PE和.net assembly的加载
    有趣的重写GetType()方法
    对Wintercn关于函数式编程的文章评论
    The experience to config Cisco 2811 for VOIP
    关于c#静态方法和实例方法的辨析和应用
    防止刷新时,密码输入框中的信息丢失
    计算百分比 JS
  • 原文地址:https://www.cnblogs.com/gmh77/p/13938721.html
Copyright © 2011-2022 走看看