zoukankan      html  css  js  c++  java
  • Gym101669L Divide and Conquer

    Link
    首先答案显然不可能是(1)
    然后有一个很显然的方法是把度数最小的点的所有边删掉,注意到总的度数为(4n-4),所以一定存在某个点度数不大于(3),因此答案不大于(3)
    那么可行的答案就只有(2,3)
    也就是说要么两棵树各割掉一条边,要么一棵树割一条边另一棵树割两条边。
    我们枚举割掉第一棵树上的哪条边,然后计算在另一棵树上分开这两个连通块所需要割掉的最小边数,这个可以用差分进行维护。
    注意如果求出来的答案为(3),那么我们还需要再在另一棵树上再枚举一遍。

    #include<cstdio>
    #include<cctype>
    #include<vector>
    const int N=300007;
    int read(){int x=0,c=getchar();while(isspace(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
    int n,ans,cnt;
    struct Tree
    {
        std::vector<int>e[N];int col[N],size[N],son[N];
        void dfs(int u,int fa){size[u]=1;for(int v:e[u])if(v^fa)if(dfs(v,u),size[u]+=size[v],size[v]>size[son[u]])son[u]=v;}
        void build(){for(int i=1,u,v;i<n;++i)u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);dfs(1,0);}
        int color(int u){int tot=0;col[u]=1;for(int v:e[u])tot+=col[v]?-1:1;return tot;}
        void reset(int u,int fa,Tree*t){t->col[u]=0;for(int v:e[u])if(v^fa)reset(v,u,t);}
        int color(int u,int fa,Tree*t){int tot=t->color(u);for(int v:e[u])if(v^fa)tot+=color(v,u,t);return tot;}
        int cal(int u,int fa,Tree*t)
        {
    	if(!u) return 0;
    	for(int v:e[u]) if(v^fa&&v^son[u]) cal(v,u,t),reset(v,u,t);
    	int tot=cal(son[u],u,t)+t->color(u)+1;
    	for(int v:e[u]) if(v^fa&&v^son[u]) tot+=color(v,u,t);
    	if(u^1) ans>tot? ans=tot,cnt=1:cnt+=ans==tot;
    	return tot-1;
        }
    }t1,t2;
    int main()
    {
        n=read(),ans=3,t1.build(),t2.build(),t1.cal(1,0,&t2);
        if(ans==3) t2.cal(1,0,&t1);
        printf("%d %d",ans,cnt);
    }
    
  • 相关阅读:
    quartz CronExpression表达式
    nginx配置文件说明
    mysql的日期输出格式列出来
    linux配置定时备份mysql数据库
    Nginx 配置
    查看mysql 服务有哪些ip地址在连接。
    对HelloWorld进行探究
    SpringBoot热部署与启动速度优化
    SpringBoot 快速入门
    初始SpringBoot
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12576337.html
Copyright © 2011-2022 走看看