• POJ 3659 Cell Phone Network


    需要考虑和节点(u)相邻的节点的选择情况,所以既要看儿子,也要看父亲。选择(u),选择(u)的儿子,选择(u)的父亲都对子树答案有影响。
    对节点(u)来说,(u)被支配的情况有三种:选择(u)自身,选择(u)的父亲,选择(u)的儿子,三种情况选择其一即可使得(u)被支配。

    状态表示:
    (f(u,0)):不选(u),选择(u)的父亲。
    (f(u,1)):选(u)
    (f(u,2)):不选(u),选择(u)的儿子。

    状态转移:
    若不选(u),选择(u)的父亲,则(u)的儿子要么选择自己来支配自身,要么选择自己的子节点来支配自身。

    [f(u,0)=sum_{j in Son(u)} min(f(j,1),f(j,2)) ]

    若选(u),则(u)的子节点可选可不选,其中不选的情况又分为:1.选择子节点支配自身。2.选择父节点支配自身。

    [f(u,1)=1+sum_{j in Son(u)} min(f(j,1),f(j,0),f(j,2)) ]

    若不选(u),选择(u)的儿子,则(u)至少需要选择某一个儿子支配,其余儿子可选可不选。
    枚举每个子节点(j)支配(u)

    [f(u,2)=min(f(u,2),f(k,1)+sum_{j in Son(u)且j e k} min(f(j,1),f(j,2))) \=min(f(u,2),f(u,0)-min(f(k,1),f(k,2))+f(k,1)) ]

    const int N=10010;
    vector<int> g[N];
    int f[N][3];
    int n;
    
    void dfs(int u,int fa)
    {
        f[u][0]=0;
        f[u][1]=1;
    
        for(int i=0;i<g[u].size();i++)
        {
            int j=g[u][i];
            if(j == fa) continue;
            dfs(j,u);
            f[u][0]+=min(f[j][1],f[j][2]);
            f[u][1]+=min(f[j][0],min(f[j][1],f[j][2]));
        }
    
        f[u][2]=INF;
        for(int i=0;i<g[u].size();i++)
        {
            int k=g[u][i];
            if(k == fa) continue;
            f[u][2]=min(f[u][2],f[u][0]-min(f[k][1],f[k][2])+f[k][1]);
        }
    }
    
    int main()
    {
        cin>>n;
    
        for(int i=0;i<n-1;i++)
        {
            int a,b;
            cin>>a>>b;
            g[a].pb(b);
            g[b].pb(a);
        }
    
        dfs(1,-1);
    
        cout<<min(f[1][1],f[1][2])<<endl;
        //system("pause");
        return 0;
    }
    
  • 相关阅读:
    同步和异步有何异同?在什么情况下分别使用他们?举例说明
    Java检查异常和非检查异常,运行时异常和非运行时异常的区别
    运行时异常与受检异常有何异同、error和exception有什么区别
    sleep() 和 wait() 有什么区别?
    final, finally, finalize的区别
    HashMap和Hashtable的区别
    & 和 && 的区别
    List集合复制
    Visual Studio 2015 Tools for Unity安装
    发布Android程序
  • 原文地址:https://www.cnblogs.com/fxh0707/p/14636432.html
Copyright © 2020-2023  润新知