zoukankan      html  css  js  c++  java
  • Codeforces Round #379 (Div. 2) E. Anton and Tree

    题意:
    给一颗树 每个节点有黑白2色
    可以使一个色块同事变色,问最少的变色次数。
    思路:
    先缩点 把一样颜色的相邻点 缩成一个
    然后新的树 刚好每一层是一个颜色。
    最后的答案就是树的直径/2

    不过我用的树上的dp,强行求了以每个点为根时树的深度
    答案就是最小的深度-1

    具体见代码:

    const int maxn = 200000 + 10;
    int n;
    int color[maxn];
    int pa[maxn];
    vector<int> G[maxn], G2[maxn];
    void init()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", color + i);
        }
        int u, v;
        for (int i = 1; i < n; i++)
        {
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
    }
    
    int find(int x) 
    { 
        return pa[x] != x ? pa[x] = find(pa[x]) : x;
    }
    
    int fa[maxn];
    void getTree()
    {
        queue<int> q;
        q.push(1);
        color[0] = -1;
        while (!q.empty())
        {
            int u = q.front(); q.pop();
            if (color[fa[u]] == color[u]) pa[u] = find(fa[u]);
            else G2[fa[pa[u]]].push_back(u);
            for (int i = 0; i < G[u].size(); i++)
            {
                int v = G[u][i];
                if (find(v) == find(fa[u])) continue;
                fa[v] = pa[u];
                q.push(v);
            }
        }
        swap(G, G2);
    }
    
    void pg()
    {
        cout << "Graph:" << endl;
        for (int i = 0; i <= n; i++)
        {
            for (int j = 0; j < G[i].size(); j++)
            {
                cout << i << " " << G[i][j] << endl;
            }
        }
    }
    
    int son1[maxn], son2[maxn]; //i节点的最大的儿子 和 次大的儿子的下标
    
    int deep[maxn]; 
    int deepFa[maxn];//i的父亲除了i以外的最深深度
    
    int d[maxn];//以i为根时树的深度 d[i] = max(deep[i], deepFa[i] + 1)
    
    int dfs(int u) //得到每个节点最深儿子的深度
    {
        deep[u] = 0;
        for (int i = 0; i < G[u].size(); i++)
        {
            int v = G[u][i];
            fa[v] = u;
            int tmp = dfs(v);
            if (tmp >= deep[u])
            {
                son2[u] = son1[u];
                son1[u] = v;
                deep[u] = tmp;
            }
            else
            {
                if (tmp > deep[son2[u]]) son2[u] = v;
            }
        }
        deep[u]++;
        return deep[u];
    }
    
    int bfs()
    {
        queue<int> q;
        for (int i = 0; i < G[1].size(); i++) q.push(G[1][i]);
        int ans = d[1] = deep[1];
        while (!q.empty())
        {
            int u = q.front(); q.pop();
            if (son1[fa[u]] == u) deepFa[u] = deep[son2[fa[u]]] + 1;
            else deepFa[u] = deep[son1[fa[u]]] + 1;
    
            deepFa[u] = max(deepFa[u], deepFa[fa[u]] + 1);
    
            d[u] = max(deep[u], deepFa[u] + 1);
            ans = min(ans, d[u]);
            for (int i = 0; i < G[u].size(); i++)
            {
                q.push(G[u][i]);
            }
        }
        return ans - 1;
    }
    
    void solve()
    {
        for (int i = 1; i <= n; i++) pa[i] = i;
        getTree();
        memset(fa, -1, sizeof(fa));
        for (int i = 0; i <= n; i++) son1[i] = son2[i] = n + 1;
        dfs(0);
        cout << bfs() << endl;
    }
    
    int main()
    {
        init();
        solve();
        return 0;
    }
  • 相关阅读:
    隐私政策
    .net打杂工程师的面试感想和总结
    xamarin调试android部署到模拟器错误记录:Deployment failed Mono.AndroidTools.InstallFailedException: Unexpected install output: Error: Could not access the Package Manager. Is the system running?
    C#位运算实际作用之操作整型某一位
    C#位运算实际运用之合并Int
    C#位运算基本概念与计算过程
    ajax异步请求302分析
    http与https区别
    html + css + jquery实现简单的进度条实例
    一个简单的彩色背景图形验证码
  • 原文地址:https://www.cnblogs.com/liangyongrui/p/6074008.html
Copyright © 2011-2022 走看看