zoukankan      html  css  js  c++  java
  • P2899 [USACO08JAN]手机网络Cell Phone Network

    题意:

    一棵 n 个点的无权树,求最⼩点覆盖

    思路:

    那么,我们考虑一个结点可以被谁染色,不难想出,可以有3种情况:被自己染色,被儿子染色,被父亲染色

    我们不妨设:

    f[i][0] 代表被自己染色      f[i][1] 代表被父亲染色       f[i][2] 代表被儿子染色

    设当前节点是 u ,儿子节点是 v

    我们来考虑下转移方程:

    1自己被自己染色

    这时我们可以想一下,u被自己染色可以由什么转移过来,如果u已经被自己染色了的话,他的儿子v可以选择自己染色,也可以选择被自己的儿子染色,当然也可以被u染色,当然,我们要选最小的,所以转移方程就是

    f[u][0] += min(f[v][0],f[v][1],f[v][2] )

    2被自己的父亲结点染色

    如果被父亲结点(fa)染色了,那么u的儿子v只能选择自己染色或者被它的儿子染色,转移方程为

    f[u][1] += min(f[v][1],f[v][0] )

    3被自己的儿子结点染色

    这是最麻烦的一种情况,因为u可能有多个儿子,只要有一个儿子自己染色了,就可以将u覆盖,这种情况就成立了

    而现在它的儿子有两种情况,分别是自己染色和被它儿子染色

    我们可以先假设每个儿子都是被它自己染色(v被自己染色)的,然后看一下u的每个儿子(v)被其儿子染色是否使结果变得更小,把能让结果更小的 自己染色(v自己染色)的儿子 替换为 被其儿子染色的儿子(v被它儿子染色)的儿子

    #include <iostream>
    #include <algorithm>
    #include <string>
    #include <string.h>
    #include <vector>
    #include <map>
    #include <stack>
    #include <set>
    #include <queue>
    #include <math.h>
    #include <cstdio>
    #include <iomanip>
    #include <time.h>
    #include <bitset>
    #include <cmath>
    
    #define LL long long
    #define INF 0x3f3f3f3f
    #define ls nod<<1
    #define rs (nod<<1)+1
    
    const double eps = 1e-10;
    const int maxn = 1e5 + 10;
    const LL mod = 1e9 + 7;
    
    int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;}
    using namespace std;
    
    struct edge {
        int v,nxt;
    }e[maxn << 1];
    
    int head[maxn];
    int cnt;
    int f[maxn][3];
    
    
    inline void add_edge(int u,int v) {
        e[++cnt].v = v;
        e[cnt].nxt = head[u];
        head[u] = cnt;
    }
    
    void dfs(int u,int fa) {
        f[u][0] = 1;
        int tot = 0;
        int g[maxn];
        for (int i = head[u];~i;i = e[i].nxt) {
            int v = e[i].v;
            if (v == fa)
                continue;
            dfs(v,u);
            f[u][0] += min(f[v][0],min(f[v][1],f[v][2]));
            f[u][1] += min(f[v][0],f[v][2]);
            f[u][2] += f[v][0];
            g[++tot] = f[v][2] - f[v][0];
        }
        if (!tot)
            f[u][2] = INF;
        else {
            sort(g+1,g+1+tot);
            for (int i = 1;i < tot;i++) {
                if (g[i] < 0)
                    f[u][2] += g[i];
                else
                    break;
            }
        }
    }
    
    
    int main() {
        cnt = 0;
        memset(head,-1, sizeof(head));
        int n;
        cin >> n;
        for (int i = 1;i < n;i++) {
            int u,v;
            cin >> u >> v;
            add_edge(u,v);
            add_edge(v,u);
        }
        dfs(1,0);
        cout << min(f[1][0],f[1][2]) << endl;
        return 0;
    }
  • 相关阅读:
    Envoy 源码分析--network L4 filter manager
    Envoy 源码分析--network
    Envoy 源码分析--buffer
    Envoy 源码分析--event
    kubeadm安装kubernetes-v1.13.1
    istio-opentracing链路追踪方案
    istio-mix介绍
    BLAKE及BLAKE2算法详解
    YIIMP矿池搭建
    NOMP矿池搭建
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/12339750.html
Copyright © 2011-2022 走看看