【CF617D】Roads in Yusland

【CF617D】Roads in Yusland

题面

description

蒯的洛谷的

题解

我们现在已经转化好了题目了,戳这里

那么我们考虑怎么求这个东西,我们先判断一下是否所有的边都能被覆盖,不行的话输出\(-1\)

再将路径\(u\rightarrow v(dep_u>dep_v)\)以其权值为关键字丢到以\(u\)为根的左偏树(小根)上,

再进行\(dfs\),合并\(x\)的所有儿子的左偏树,对于点\(x\),我们能选则选,

还有打标记等细节,详见代码。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring> 
#include <cmath> 
#include <algorithm>
using namespace std; 
namespace IO { 
    const int BUFSIZE = 1 << 20; 
    char ibuf[BUFSIZE], *is = ibuf, *it = ibuf; 
    inline char gc() { 
        if (is == it) it = (is = ibuf) + fread(ibuf, 1, BUFSIZE, stdin); 
        return *is++; 
    } 
} 
inline int gi() {
    register int data = 0, w = 1;
    register char ch = 0;
    while (ch != '-' && (ch > '9' || ch < '0')) ch = IO::gc();
    if (ch == '-') w = -1 , ch = IO::gc();
    while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = IO::gc();
    return w * data;
} 
const int MAX_N = 3e5 + 5; 
struct Graph { int to, next; } e[MAX_N << 1];
int fir[MAX_N], e_cnt; 
void clearGraph() { memset(fir, -1, sizeof(fir)); e_cnt = 0; } 
void Add_Edge(int u, int v) { e[e_cnt] = (Graph){v, fir[u]}; fir[u] = e_cnt++; }
struct chain { int u, v, w; } a[MAX_N]; 
int N, M, c[MAX_N], dep[MAX_N];
long long ans = 0; 
void dfs(int x, int f) {
    dep[x] = dep[f] + 1; 
    for (int i = fir[x]; ~i; i = e[i].next) {
        int v = e[i].to; if (v == f) continue;
        dfs(v, x), c[x] += c[v]; 
    } 
} 
struct Node {
    int ls, rs, dis;
    int v, ed, tag;
} t[MAX_N]; 
int rt[MAX_N];
void puttag(int x, int v) { t[x].tag += v, t[x].v += v; } 
void pushdown(int x) {
    if (!t[x].tag) return ;
    if (t[x].ls) puttag(t[x].ls, t[x].tag); 
    if (t[x].rs) puttag(t[x].rs, t[x].tag); 
    t[x].tag = 0; 
} 
int merge(int x, int y) {
    if (!x || !y) return x + y; 
    pushdown(x), pushdown(y); 
    if (t[x].v > t[y].v) swap(x, y); 
    t[x].rs = merge(t[x].rs, y); 
    if (t[t[x].ls].dis < t[t[x].rs].dis) swap(t[x].ls, t[x].rs); 
    t[x].dis = t[t[x].rs].dis + 1; 
    return x; 
} 
void solve(int x, int f) { 
    for (int i = fir[x]; ~i; i = e[i].next)
        if (e[i].to != f) {
            solve(e[i].to, x); 
            rt[x] = merge(rt[e[i].to], rt[x]); 
        }
    if (x == 1) return ; 
    while (dep[t[rt[x]].ed] >= dep[x]) rt[x] = merge(t[rt[x]].ls, t[rt[x]].rs); 
    int w = t[rt[x]].v; 
    ans += w, puttag(rt[x], -w); 
} 
int main () { 
#ifndef ONLINE_JUDGE 
    freopen("cpp.in", "r", stdin); 
#endif
    clearGraph(); 
    N = gi(), M = gi();
    for (int i = 1; i < N; i++) {
        int u = gi(), v = gi(); 
        Add_Edge(u, v), Add_Edge(v, u); 
    } 
    for (int i = 1; i <= M; i++) a[i] = (chain){gi(), gi(), gi()}; 
    for (int i = 1; i <= M; i++) c[a[i].u]++, c[a[i].v]--; 
    dfs(1, 0); 
    for (int i = 2; i <= N; i++) if (c[i] <= 0) return puts("-1") & 0; 
    for (int i = 1; i <= M; i++) t[i] = (Node){0, 0, 0, a[i].w, a[i].v, 0}, rt[a[i].u] = merge(rt[a[i].u], i);
    solve(1, 0); 
    cout << ans << endl; 
    return 0; 
} 

跑到洛谷\(rank1\)纪念一下:

img

好像还是cf的\(rank1\)呢qaq:

img1

posted @ 2019-03-12 22:10  heyujun  阅读(377)  评论(4编辑  收藏  举报