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

析:很明显这是一个树上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;
}

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

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

    Cow Marathon Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 5496   Accepted: 2685 Case ...

  2. POJ 1985 Cow Marathon (模板题)(树的直径)

    <题目链接> 题目大意: 给定一颗树,求出树的直径. 解题分析:树的直径模板题,以下程序分别用树形DP和两次BFS来求解. 树形DP: #include <cstdio> #i ...

  3. 题解报告:poj 1985 Cow Marathon(求树的直径)

    Description After hearing about the epidemic of obesity in the USA, Farmer John wants his cows to ge ...

  4. POJ 1985 Cow Marathon (求树的直径)

    Description After hearing about the epidemic of obesity in the USA, Farmer John wants his cows to ge ...

  5. POJ 3162.Walking Race 树形dp 树的直径

    Walking Race Time Limit: 10000MS   Memory Limit: 131072K Total Submissions: 4123   Accepted: 1029 Ca ...

  6. poj 1985 Cow Marathon

    题目连接 http://poj.org/problem?id=1985 Cow Marathon Description After hearing about the epidemic of obe ...

  7. poj 1985 Cow Marathon 树的直径

    题目链接:http://poj.org/problem?id=1985 After hearing about the epidemic of obesity in the USA, Farmer J ...

  8. poj 1985 Cow Marathon【树的直径裸题】

    Cow Marathon Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 4185   Accepted: 2118 Case ...

  9. POJ 1985 Cow Marathon && POJ 1849 Two(树的直径)

    树的直径:树上的最长简单路径. 求解的方法是bfs或者dfs.先找任意一点,bfs或者dfs找出离他最远的那个点,那么这个点一定是该树直径的一个端点,记录下该端点,继续bfs或者dfs出来离他最远的一 ...

随机推荐

  1. IP 地址 与 DNS

    IP地址转化 192.168.10.1 十进制,点分十进制地址 32位二进制数字序列,四段,八位 十进制与二进制转换00000000 = 000000001 = 2 * 0 = 100000010 = ...

  2. Druid.io系列(一):简介

    原文链接: https://blog.csdn.net/njpjsoftdev/article/details/52955676 Druid.io(以下简称Druid)是面向海量数据的.用于实时查询与 ...

  3. HDU1869 六度分离

    /* 六度分离 Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  4. OD 实验(十八) - 简单注册机的编写

    程序: 运行 这是一个注册机 随便输入点内容,点击 Check 弹出错误的对话框 逆向: 用 OD 载入程序 在文本框处下断点 按 Alt+B 查看断点 这个断点在动态链接库那里 跑一下程序,输入内容 ...

  5. redis 创建集群时 出现的错误解决方式

    1. 创建集群时报以下错误 (1)错误1 ./redis-trib.rb create --replicas 1 XXXXXX:5301 XXXXXX:5302 XXXXXX:5303 XXXXXX: ...

  6. C#实现并口输出输入高低电位

    PC并行口各阵脚定义: 1.选通,PC->Printer 2-9 数据(D0-D7) 10.应答(ACK),Printer->PC 11.忙(BUSY),Printer->PC 12 ...

  7. leetcode125

    public class Solution { Stack<char> S = new Stack<char>(); Queue<char> Q = new Que ...

  8. GNU/Linux操作系统总览

    计算机科学本科的专业课包括高等数学.离散数学.模拟电子技术.数字电子技术.微机原理.汇编语言原理.高级程序语言.操作系统原理.高级编译原理.嵌入式原理.网络原理.计算机组成与结构等诸多科目.GNU计算 ...

  9. Balls(poj 3783)

    The classic Two Glass Balls brain-teaser is often posed as: “Given two identical glass spheres, you ...

  10. 【302】C# TreeView 控件使用说明

    参考:C# 中treeview 树节点图标的动态加载,及选中时图标改变 参考:C# TreeView 控件的综合使用方法 参考:TreeView 类 参考:TreeNode 类 1. 添加根和子级 通 ...