POJ 1985 Cow Marathon (树形DP,树的直径)

题意:给定一棵树,然后让你找出它的直径,也就是两点中的最远距离。

析:很明显这是一个树上DP,应该有三种方式,分别是两次DFS,两次BFS,和一次DFS,我只写了后两种。

代码如下:

两次BFS:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>

using namespace std;
const int maxn = 1e5 + 5;
int d[maxn];
bool vis[maxn], vvis[maxn];//vis是BFS的标记,vvis是总的标记
vector<int> G[maxn], w[maxn];
//思路就是先在树上找一个点,然后从这个点开始找,找最远的点,
//然后两从最远的点找最远的点,这个所有点中的最大值就是树的直径
//d[i]表示到结点 i 的最长距离
int bfs(int root){
    memset(vis, false, sizeof(vis));
    memset(d, 0, sizeof(d));
    queue<int> q;
    q.push(root);
    int ans = root, m = 0;
    vis[root] = vvis[root] = true;
    while(!q.empty()){
        root = q.front();   q.pop();
        for(int i = 0; i < G[root].size(); ++i){
            int u = G[root][i];
            if(vis[u])  continue;
            q.push(u);
            vis[u] = vvis[u] = true;
            d[u] = d[root] + w[root][i];
            if(d[u] > m){
                ans = u;
                m = d[u];
            }
        }
    }
    return ans;
}

void init(int n){
    for(int i = 1; i <= n; ++i){
        G[i].clear();
        w[i].clear();
        vvis[i] = false;
    }
}

int main(){
    int n, m, u, v, l;
    char ch;
    while(cin >> n >> m){
        init(n);
        while(m--){
            scanf("%d %d %d %c", &u, &v, &l, &ch);
            G[u].push_back(v);  w[u].push_back(l);
            G[v].push_back(u);  w[v].push_back(l);
        }

        int ans = 0;
        for(int i = 1; i <= n; ++i)
            if(!vvis[i])  ans = max(ans, d[bfs(bfs(i))]);//两次BFS,第一次是找最远的点,第二次是找最远点的最远点
        cout << ans << endl;
    }
    return 0;
}

一次DFS:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>

using namespace std;
const int maxn = 1e5 + 5;
int f[maxn], g[maxn], ll[maxn];
vector<int> G[maxn], w[maxn];
//思路主要是找一个点的最远点加次远点就是树的直径

int dfs(int root, int fa){
    if(f[root] != -1)  return f[root];
    if(!G[root].size())  return f[root] = 0;
    int m = 0, ans = root;
    for(int i = 0; i < G[root].size(); ++i){
        int u = G[root][i];
        if(u == fa)  continue;
        if(dfs(u, root) + w[root][i] > m){
            m = f[u] + w[root][i];
            ans = u;
        }
    }

    ll[root] = ans; int  mm = 0;
    for(int i = 0; i < G[root].size(); ++i){
        int u = G[root][i];
        if(u == fa)  continue;
        if(f[u] + w[root][i] > mm && u != ll[root])
            mm = f[u] + w[root][i];
    }
    g[root] = mm;
    return f[root] = m;
}

void init(int n){
    for(int i = 1; i <= n; ++i){
        G[i].clear();
        w[i].clear();
        f[i] = g[i] = ll[i] = -1;
    }
}

int main(){
    int n, m, u, v, l;
    char ch;
    while(cin >> n >> m){
        init(n);
        while(m--){
            scanf("%d %d %d %c", &u, &v, &l, &ch);
            G[u].push_back(v);  w[u].push_back(l);
            G[v].push_back(u);  w[v].push_back(l);
        }

        int ans = 0;
        for(int i = 1; i <= n; ++i)
            if(f[i] == -1)  dfs(i, -1);
        for(int i = 1; i <= n; ++i)  ans = max(ans, f[i]+g[i]);
            cout << ans << endl;
    }
    return 0;
}
时间: 2024-08-28 23:00:10

POJ 1985 Cow Marathon (树形DP,树的直径)的相关文章

poj:1985:Cow Marathon(求树的直径)

Cow Marathon Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 5496   Accepted: 2685 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 com

poj 1985 Cow Marathon 【树的直径】

题目:poj 1985 Cow Marathon 题意:给出一个树,让你求树的直径. 分析: 树的直径:树上两点之间的最大距离. 我们从任意一点出发,BFS一个最远距离,然后从这个点出发,在BFS一个最远距离,就是树的直径. AC代码: /* POJ:1985 Cow Marathon 2014/10/12/21:18 Yougth*/ #include <cstdio> #include <iostream> #include <algorithm> #include

poj 1985 Cow Marathon

题目连接 http://poj.org/problem?id=1985 Cow Marathon 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 ro

POJ 1985 Cow Marathon(树的直径)

http://poj.org/problem?id=1985 题意: 有一个树结构, 给你树的全部边(u,v,cost), 表示u和v两点间有一条距离为cost的边. 然后问你该树上最远的两个点的距离是多少?(即树的直径) 分析: 对于树的直径问题, <<算法导论>>(22 2-7)例题有说明. 详细解法: 首先从树上随意一个点a出发, (BFS)找出到这个点距离最远的点b. 然后在从b点出发(BFS)找到距离b点最远的点c. 那么bc间的距离就是树的直径. 证明: 1.    a

BZOJ 3363 POJ 1985 Cow Marathon 树的直径

题目大意:给出一棵树.求两点间的最长距离. 思路:裸地树的直径.两次BFS,第一次随便找一个点宽搜.然后用上次宽搜时最远的点在宽搜.得到的最长距离就是树的直径. CODE: #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 80010 using namespace std; int

POJ 1985 Cow Marathon【树的直径】

题目大意:给你一棵树,要你求树的直径的长度 思路:随便找个点bfs出最长的点,那个点一定是一条直径的起点,再从那个点BFS出最长点即可 以下研究了半天才敢交,1.这题的输入格式遵照poj1984,其实就是把后面的字母无视即可 2.这题数据量没给,所以把数组开得很大才敢交TUT #include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <

POJ 1849 Two (树形dp 树的直径 两种方法)

Two Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 1232   Accepted: 619 Description The city consists of intersections and streets that connect them. Heavy snow covered the city so the mayor Milan gave to the winter-service a list of st

codeforces 455C C. Civilization(树形dp+树的直径+并查集)

题目链接: codeforces 455C 题目大意: 给出一些点,他们之间初始存在一些边,给出两种操作,第一种是查询某个点所在的树的直径,另一种是将两个树合并,要求使合并后的树的直径最小. 题目分析: 首先算取没做操作前的连通块里的树的直径,也就是先dfs一遍,找到深度最大的点,然后从这个点再搜,找到的最远的距离就是这棵树的直径,因为可以证明从根搜深度最大的点一定是树的直径的一个端点,因为它可以通过到达次大的深度的点或者找到与它公共祖先不在根处的获得树的直径. 然后每次合并,我们可以知道得到的

POJ 1655 Balancing Act (树形dp 树的重心)

Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10596   Accepted: 4398 Description Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a forest: a collection of one or m