• luogu_P5258 旅行时的困惑


    https://www.luogu.org/problem/P5258

    题目描述

    Waldives 有 NN 个小岛。目前的交通系统中包含 N-1N1 条快艇专线,每条快艇专线连接两个岛。这 N-1N1条快艇专线恰好形成了一棵树。

    由于特殊的原因,所有 N-1N1 条快艇专线都是单向的。这导致了很多岛屿之间 不能相互到达。因此,Waldives 政府希望新建一些公交线路,使得建设完毕后,任意两个小岛都可以互相到达。为了节约开支,政府希望建设最少的公交线路。

    同时,出于规划考虑,每一条公交线路都有如下的要求:

    1、每一条交通线路包含若干条连续的快艇专线,你可以认为一条公交线路 对应树上的一条路径,而其所包含的若干快艇专线则对应树上被这条路 径所覆盖的树边(也就是之前已经存在的某个快艇专线);

    2、显然一条交通线路只能覆盖树上任意一条边至多一次;

    3、公交线路中所包含的每一个快艇专线都是有方向的,并且与其所覆盖的 树边的方向相反;

    4、不同的公交线路可以覆盖树上相同的点或者相同的边。

    Waldives 的 NN 个岛屿分别从 00 到 N-1N1 编号。现在给出 Waldives 已有的快艇专线信息,请计算最少所需要新建的交通线路的数量。

    输入格式

    第一行包含一个整数 NN。

    接下来 N-1N1行,每行包含两个整数 x,~yx, y。表示存在一条从岛屿 xx 开往岛屿 yy 的快艇专线。

    输出格式

    输出一行一个整数,表示需要建设的最少的交通线路数量。


    注意“不同的公交线路可以覆盖树上相同的点或者相同的边”

    这样就可以树形dp了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    
    #define ri register int
    #define u int
    #define NN 1000005
    
    namespace opt {
    
        inline u in() {
            u x(0),f(1);
            char s=getchar();
            while(s<'0'||s>'9') {
                if(s=='-') {
                    f=-1;
                }
                s=getchar();
            }
            while(s>='0'&&s<='9') {
                x=(x<<1)+(x<<3)+s-'0';
                s=getchar();
            }
            return x*f;
        }
    
    }
    
    namespace mainstay {
    
        u N,ans,in[NN],out[NN];
    
        u cnt,h[NN];
    
        struct node {
            u to,next;
        } a[NN<<1];
    
        inline void add(const u &x,const u &y) {
            a[++cnt].next=h[x],a[cnt].to=y,h[x]=cnt;
        }
    
        void dfs(const u &x,const u &prt) {
            for(ri i(h[x]); i; i=a[i].next) {
                u _y(a[i].to);
                if(_y^prt) {
                    dfs(_y,x);
                    if(i&1) {
                        ans+=out[_y];
                        in[x]+=std::max(1,in[_y]);
                    } else {
                        ans+=in[_y];
                        out[x]+=std::max(1,out[_y]);
                    }
                }
            }
            u _mi(std::min(in[x],out[x]));
            ans+=_mi,in[x]-=_mi,out[x]-=_mi;
        }
    
        inline void solve() {
            N=opt::in();
            for(ri i(1); i<N; ++i) {
                u _a(opt::in()+1),_b(opt::in()+1);
                add(_a,_b),add(_b,_a);
            }
            dfs(1,0);
            printf("%d",ans+std::max(in[1],out[1]));
        }
    
    }
    
    int main() {
    
        //freopen("x.txt","r",stdin);
        mainstay::solve();
    
    }
  • 相关阅读:
    菖蒲河公园-中山公园-天安门广场一日游
    LeetCode 485 Max Consecutive Ones
    LeetCode 766. Toeplitz Matrix
    LeetCode 566 Reshape the Matrix
    LeetCode 561. Array Partition I
    算法学习系列之(1):常用算法设计方法
    纪念2017,展望2018
    Java server数据之(4):Redis鸟瞰
    《机器学习》读书笔记-第一章 引言
    node.js实践第二天
  • 原文地址:https://www.cnblogs.com/ling-zhi/p/11739350.html
Copyright © 2020-2023  润新知