• [BZOJ1060] [ZJOI2007]时态同步


    Description

      小Q在电子工艺实习课上学习焊接电路板。一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数
    字1,2,3….进行标号。电路板的各个节点由若干不相交的导线相连接,且对于电路板的任何两个节点,都存在且仅
    存在一条通路(通路指连接两个元件的导线序列)。在电路板上存在一个特殊的元件称为“激发器”。当激发器工
    作后,产生一个激励电流,通过导线传向每一个它所连接的节点。而中间节点接收到激励电流后,得到信息,并将
    该激励电流传向与它连接并且尚未接收到激励电流的节点。最终,激烈电流将到达一些“终止节点”——接收激励
    电流之后不再转发的节点。激励电流在导线上的传播是需要花费时间的,对于每条边e,激励电流通过它需要的时
    间为te,而节点接收到激励电流后的转发可以认为是在瞬间完成的。现在这块电路板要求每一个“终止节点”同时
    得到激励电路——即保持时态同步。由于当前的构造并不符合时态同步的要求,故需要通过改变连接线的构造。目
    前小Q有一个道具,使用一次该道具,可以使得激励电流通过某条连接导线的时间增加一个单位。请问小Q最少使用
    多少次道具才可使得所有的“终止节点”时态同步?

    Input

      第一行包含一个正整数N,表示电路板中节点的个数。第二行包含一个整数S,为该电路板的激发器的编号。接
    下来N-1行,每行三个整数a , b , t。表示该条导线连接节点a与节点b,且激励电流通过这条导线需要t个单位时

    Output

      仅包含一个整数V,为小Q最少使用的道具次数

    Sample Input

    3
    1
    1 2 1
    1 3 3

    Sample Output

    2

    HINT

    N ≤ 500000,te ≤ 1000000


    其实还是很水的。

    设$large f[i]$表示以i为根的字数的叶子的时态同步的最小花费。

    怎么转移?

    贪心地想,我们肯定要让$x$的所有子树的同步时态和$x$的所有子树中同步后的时态最长的一样就行了。

    所以设$tmp$为$x$的所有子树中的同步时态最长的。

    那么$large f[i] += f[j] + tmp - g[j]$,其中$large g[j]$表示以j为根的子树的最大时态。

    最后把所有的$g[j]$改成$tmp$就行了。

    其实一开始写对了然后和大样例一直不对调了好久, 最后发现没开long long


    #include <iostream>
    #include <cstdio>
    using namespace std;
    #define reg register
    #define int long long
    inline int read() {
        int res = 0;char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48), ch=getchar();
        return res;
    }
    #define N 500005
    int n, S;
    struct edge {
        int nxt, to, val;
    }ed[N*2];
    int head[N], cnt;
    int deg[N];
    inline void add(int x, int y, int z)
    {
        ed[++cnt] = (edge){head[x], y, z};
        head[x] = cnt;
        deg[y] ++;
    }
    int f[N], g[N];
    int dis[N];
    
    void dfs(int x, int fa, int d)
    {
        dis[x] = d;
        for (reg int i = head[x] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if (to == fa) continue;
            dfs(to, x, d + ed[i].val);
        }
    }
    
    void dp(int x, int fa)
    {
        if (deg[x] == 1) g[x] = dis[x];
        for (reg int i = head[x] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if (to == fa) continue;
            dp(to, x);
            g[x] = max(g[x], g[to]);
        }
        for (reg int i = head[x] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if (to == fa) continue;
            f[x] += f[to] + g[x] - g[to];
            g[to] = g[x];
        }
    }
    
    signed main()
    {
        n = read(), S = read();
        for (reg int i = 1 ; i < n ; i ++)
        {
            int x = read(), y = read(), z = read();
            add(x, y, z), add(y, x, z);
        }
        dfs(S, 0, 0);
        dp(S, 0);
        printf("%lld
    ", f[S]);
        return 0;
    }
  • 相关阅读:
    Android Sqlite 增删改查
    Android SQLiteOpenHelper Sqlite数据库升级onUpgrade
    Android SQLiteOpenHelper Sqlite数据库的创建与打开
    Android Xml,PullParser,解析
    Android Xml文件生成,Xml数据格式写入
    Android Studio生成get,set,tostring,构造方法
    Android SharedPreference
    Android 文件模式
    Android 权限的由来
    C++ essentials 之 union
  • 原文地址:https://www.cnblogs.com/BriMon/p/9593402.html
Copyright © 2020-2023  润新知