• [贪心]JZOJ 3230 【佛山市选2013】树环转换


    Description

    给定一棵N个节点的树,去掉这棵树的一条边需要消耗值1,为这个图的两个点加上一条边也需要消耗值1。树的节点编号从1开始。在这个问题中,你需要使用最小的消耗值(加边和删边操作)将这棵树转化为环,不允许有重边。

    环的定义如下:

    (1)该图有N个点,N条边。

    (2)每个顶点的度数为2。

    (3)任意两点是可达的。

    树的定义如下:

    (1)该图有N个点,N-1条边。

    (2)任意两点是可达的。
     

    Input

    第一行是一个整数N代表节点的个数。

    接下来N-1行每行有两个整数U, V(1 ≤ U, V ≤ N),表示双向边(U, V)

    Output

    输出把树转化为环的最小消耗值。
     

    Sample Input

    4
    1 2
    2 3
    2 4

    Sample Output

    3
     

    Data Constraint

    对于20%的数据,有1≤N≤10。

    对于100%的数据,有1≤N≤1000000。

    分析

    早上写的时候想的是奇怪的DP

    然后搞了一阵子发现可以贪心?

    只有一个儿子的节点则保留不变,值上传

    两个儿子的节点可以断开与父亲的联系,将子树中所有点连成一条链的代价和断开再连接的代价加入答案

    三及以上个儿子的节点可以通过断开若干个儿子的关系转变成两个儿子的状态

    这里默认树根是某条链的一端,所以如果树根属于后两种状态时,无需加上断开和连接的代价

    最后不要忘了加连接链两端的代价1

    #include <iostream>
    #include <cstdio>
    using namespace std;
    const int N=1e6+10;
    struct Graph {
        int v,nx;
    }g[2*N];
    int cnt,list[N];
    int n,ans;
    int f[N];
    int stk[N][3],top;
    bool b[N];
    
    void Add(int u,int v) {
        g[++cnt]=(Graph){v,list[u]};list[u]=cnt;
        g[++cnt]=(Graph){u,list[v]};list[v]=cnt;
    }
    
    void DFS() {
        stk[++top][0]=1;stk[top][1]=0;stk[top][2]=0;
        while (top) {
            int u=stk[top][0];
            if (!list[u]) {
                if (stk[top][2]>=2) ans+=f[u]+(stk[top][1]!=0?2:0);
                b[u]=stk[top][2]<2;
                top--;
                u=stk[top][0];
                if (b[g[list[u]].v]) {
                    stk[top][2]++;
                    f[u]+=f[g[list[u]].v];
                    if (stk[top][2]>2) f[u]+=2;
                }
                list[u]=g[list[u]].nx;
            }
            for (int i=list[u];i;i=list[u]=g[i].nx)
                if (g[i].v!=stk[top][1]) {
                    stk[++top][0]=g[i].v,stk[top][1]=u,stk[top][2]=0;
                    break;
                }    
        }
    }
    
    int main() {
        scanf("%d",&n);
        for (int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),Add(u,v);
        DFS();
        printf("%d",ans+1);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    C# 日期格式化的中的 正斜杠的问题
    JQuery中如何click中传递参数
    《启示录:打造用户喜爱的产品》—— 读书笔记
    json串的使用
    谷歌浏览器怎么调试js
    web页面布局思想
    js或者cs代码拼接html
    筛选DataTable数据的方法
    Ajax的简单小例子
    简单的javascript例子
  • 原文地址:https://www.cnblogs.com/mastervan/p/11107782.html
Copyright © 2020-2023  润新知