1131时态同步题解

· · 个人记录

P1131题解

首先我们可以发现给出的是一棵树, 而以"激发结点"为根的话"终止结点"就是叶子结点.

注意激发结点只有一个所以这题可做...

(一开始以为多个激发结点终止结点还不一定在叶子上然后推了好久发现有可能出现无

解的情况, 后来仔细读题之后发现就是个思博题QAQ(论不仔细读题的危害.png))

我们发现只要让所有子节点的到达时间都同步为耗时最多的那个子节点所需的时间即可,

所以我们对每个节点记录两个信息: 以该结点为根的子树同步后总的耗时与同步时态所需的fix次数.

这样就可以比较方便地进行转移了.

还有就是答案有可能炸

int int ...要开 longlong longlong

代码:

#include <bits/stdc++.h>
const int MAXN=500010;
struct Edge {
    int from;
    int to;
    int dis;
    Edge* next;
};
Edge E[MAXN*2];
Edge* head[MAXN];
Edge* top=E;
int n;
int root;
long long dp[MAXN];
long long clk[MAXN];
inline void DFS(int root,int prt) {
    for(Edge* i=head[root]; i!=NULL; i=i->next) {
        if(i->to!=prt) {
            DFS(i->to,root);
            dp[root]+=dp[i->to];
            clk[root]=std::max(clk[root],clk[i->to]+i->dis);
        }
    }
    for(Edge* i=head[root]; i!=NULL; i=i->next)
        if(i->to!=prt)
            dp[root]+=clk[root]-(clk[i->to]+i->dis);
}
inline void Insert(int from,int to,int dis) {
    top->to=to;
    top->dis=dis;
    top->from=from;
    top->next=head[from];
    head[from]=top++;
}
inline void Initialize() {
    int a,b,c;
    scanf("%d",&n);
    scanf("%d",&root);
    for(int i=1; i<n; i++) {
        scanf("%d%d%d",&a,&b,&c);
        Insert(a,b,c);
        Insert(b,a,c);
    }
}
int main() {
    Initialize();
    DFS(root,0);
    printf("%lld\n",dp[root]);
    return 0;
}