解题报告 『[NOI2003]逃学的小孩(树上操作)』

原题地址

今天翻看集训队巨佬写的一篇有关于树形动规的论文时看到了这道题,但感觉并不需要用动规,求出树的直径再暴力枚举一下就搞出来了。

其实是因为我太弱了,看不懂大佬在写什么orz

代码实现如下:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, a, b) for (register int i = a; i <= b; i++)

const int inf = 0x3f3f3f3f, maxn = 2e5 + 5;

int n, m, ans, tmp, str, end, num_edge = 0;
int dis1[maxn], dis2[maxn], head[maxn];

struct node {
    int to, dis, nxt;
}edge[maxn << 1];

int MIN(int a, int b) {return a < b ? a : b;}

void origin() {
    memset(dis1, 0, sizeof(head));
    memset(dis2, 0, sizeof(head));
    memset(head, -1, sizeof(head));
}

int read() {
    int x = 0, flag = 0;
    char ch = ' ';
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') {
        flag = 1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + ch - '0';
        ch = getchar();
    }
    return flag ? -x : x;
}

void addedge(int from, int to, int dis) {
    edge[++num_edge].nxt = head[from];
    edge[num_edge].to = to;
    edge[num_edge].dis = dis;
    head[from] = num_edge;
}

void dfs1(int u, int fa) {
    for (register int i = head[u]; ~i; i = edge[i].nxt) {
        int v = edge[i].to;
        if (v == fa) continue;
        dis1[v] = dis1[u] + edge[i].dis;
        if (dis1[v] > dis1[str]) str = v;
        dfs1(v, u);
    }
}

void dfs2(int u, int fa) {
    for (register int i = head[u]; ~i; i = edge[i].nxt) {
        int v = edge[i].to;
        if (v == fa) continue;
        dis2[v] = dis2[u] + edge[i].dis;
        if (dis2[v] > dis2[end]) end = v;
        dfs2(v, u);
    }
}

void dfs3(int u, int fa) {
    for (register int i = head[u]; ~i; i = edge[i].nxt) {
        int v = edge[i].to;
        if (v == fa) continue;
        dis1[v] = dis1[u] + edge[i].dis;
        dfs3(v, u);
    }
}

void dfs4(int u, int fa) {
    for (register int i = head[u]; ~i; i = edge[i].nxt) {
        int v = edge[i].to;
        if (v == fa) continue;
        dis2[v] = dis2[u] + edge[i].dis;
        dfs4(v, u);
    }
}

void write(int x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9) write(x / 10);
    putchar(x % 10 + '0');
}

signed main() {
    origin();
    n = read(), m = read();
    rep(i, 1, m) {
        int u, v, w;
        u = read(), v = read(), w = read();
        addedge(u, v, w);
        addedge(v, u, w);
    }
    dfs1(1, 0);
    dfs2(str, 0);
    ans = dis2[end];
    memset(dis1, 0, sizeof(head));
    memset(dis2, 0, sizeof(head));
    dfs3(str, 0);
    dfs4(end, 0);
    rep(i, 1, n) {
        int flag = MIN(dis1[i], dis2[i]);
        if (flag > tmp) tmp = flag;
    }
    ans += tmp;
    write(ans);
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Kirisame-Marisa/p/10774770.html