poj1985 Cow Marathon (the diameter of the tree)

Cow Marathon

Time Limit: 2000MS   Memory Limit: 30000K
Total Submissions:9653   Accepted: 4411
Case Time Limit: 1000MS

Description

After hearing about the epidemic of obesity in the USA, Farmer John wants his cows to get more exercise, so he has committed to create a bovine marathon for his cows to run. The marathon route will include a pair of farms and a path comprised of a sequence of roads between them. Since FJ wants the cows to get as much exercise as possible he wants to find the two farms on his map that are the farthest apart from each other (distance being measured in terms of total length of road on the path between the two farms). Help him determine the distances between this farthest pair of farms. 

Input

* Lines 1.....: Same input format as "Navigation Nightmare".

Output

* Line 1: An integer giving the distance between the farthest pair of farms. 

Sample Input

7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S

Sample Output

52

Hint

The longest marathon runs from farm 2 via roads 4, 1, 6 and 3 to farm 5 and is of length 20+3+13+9+7=52. 

Source

USACO 2004 February

Question meaning: find the diameter of the tree, template question

There are two ways to find the diameter of the tree

(1) Explanation of tree dp method: https://saoka.blog.luogu.org/shu-di-zhi-jing

Array definition:

dp[x]: the distance from the node furthest from x to x in the subtree rooted at x

f[x]: the length of the longest one in all chains passing through point x

edge(u,v): the path length from node u to node v

Ideas:

  • Start from the leaf nodes and merge upwards to find the d[x] for each node x. The specific operation can be through enumerating each edge of x and then transferring through the transition equation:

    dp[x] = max(dp[v_i]+edge(x,v_i), dp[x])

  • Then consider how to find f[x]. If v1​ and v2​ are respectively the farthest and second-distant nodes that can be reached from node x, then we can easily get that the longest chain through x is determined by (x,v1​) and (x,v2​ ) consist of. So when we are seeking d[x], if we find a point that can update d[x], then we add these two d[] values ​​together, so that we can ensure that we can get the farthest point and the second farthest point. point.

//树形dp
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;

int head[N], tot, ans;
int dp[N]; //以x为根的子树中,与x最远的节点到x的距离
bool vis[N];

struct Edge {
    int to, w, next;
} edge[M];

void init() {
    tot = 0;
    memset(head, -1, sizeof(head));
}

void addedge(int u, int v, int w) {
    edge[tot].to = v;
    edge[tot].w = w;
    edge[tot].next = head[u];
    head[u] = tot++;
}

void dfs(int u) {
    vis[u] = 1;
    for(int i = head[u]; ~i; i = edge[i].next) {
        int v = edge[i].to;
        if(vis[v]) continue;
        dfs(v);
        //设v1、v2分别为从节点x出发能走到的最远、次远节点,那么经过x的最长链是由(x,v1)和(x,v2)组成的
        //在求d[x]的时候,如果找到了一个点能够更新d[x], 那么就把这两个d[]值相加,这样一定可以保证能够取到最远点和次远点
        ans = max(ans, dp[u] + dp[v] + edge[i].w);
        dp[u] = max(dp[u], dp[v] + edge[i].w);
    }
}

int main() {
    char c;
    int n, m, u, v, w;
    init();
    scanf("%d%d", &n, &m);
    while(m--) {
        scanf("%d%d%d", &u, &v, &w);
        cin >> c;
        addedge(u, v, w);
        addedge(v, u, w);
    }
    for(int i = 1; i <= n; ++i) vis[i] = 0;
    for(int i = 1; i <= n; ++i) dp[i] = 0;
    dfs(1);
    printf("%d\n", ans);
    return 0;
}

(2) Two dfs seeking explanations: https://www.cnblogs.com/handsome-zyc/p/11237529.html

Method: start from any point P, find the farthest point Q from it, then start from point Q, find the farthest point W from it, the distance from W to Q is the diameter of

The proof is as follows:

① If P is already on the diameter, according to the definition of the diameter of the tree, we know that Q is also on the diameter and is an end point of the diameter

②If P is not on the diameter, we use the contradiction method, assuming that WQ is not the diameter at this time, and AB is the diameter

--->If AB and PQ have intersection point C, since P is the farthest from Q, then PC+CQ>PC+CA, so CQ>CA, it is easy to get CQ+CB>CA+CB, that is, CQ+CB>AB, It is contradictory to the diameter of AB, which is not true, as shown in the figure below (where AB and PQ are not necessarily straight lines, they are drawn as straight lines for convenience):

--->If there is no intersection between AB and PQ, M is any point on AB and N is any point on PQ. First of all, it is still NP+NQ>NQ+MN+MB, and at the same time subtracting NQ, we get NP>MN+MB. It is easy to know that NP+MN>MB, so NP+MN+MA>MB+MA,

That is, NP+MN+MA>AB, and AB is a diameter contradiction, so this situation is not true, as shown in the following figure:

 

//两次dfs
//先从任意一点P出发,找离它最远的点Q,再从点Q出发,找离它最远的点W,W到Q的距离就是是的直径
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;

int head[N], tot, dis[N], ans, id;

struct Edge {
    int to, w, next;
} edge[M];

void init() {
    tot = 0;
    memset(head, -1, sizeof(head));
}

void addedge(int u, int v, int w) {
    edge[tot].to = v;
    edge[tot].w = w;
    edge[tot].next = head[u];
    head[u] = tot++;
}

void dfs(int u, int fa) {
    if(ans < dis[u]) {
        ans = dis[u];
        id = u;
    }
    for(int i = head[u]; ~i; i = edge[i].next) {
        int v = edge[i].to;
        if(v == fa) continue;
        dis[v] = dis[u] + edge[i].w;
        dfs(v, u);
    }
}

int main() {
    char c;
    int n, m, u, v, w;
    init();
    scanf("%d%d", &n, &m);
    while(m--) {
        scanf("%d%d%d", &u, &v, &w);
        cin >> c;
        addedge(u, v, w);
        addedge(v, u, w);
    }
    for(int i = 1; i <= n; ++i) dis[i] = 0;
    ans = 0;
    dfs(1, 0);
    ans = 0, dis[id] = 0;
    dfs(id, 0);
    printf("%d\n", ans);
    return 0;
}

 

Guess you like

Origin blog.csdn.net/weixin_43871207/article/details/110562719