【问题描述】
n 个小朋友在玩传球。 小朋友们用 1 到 n 的正整数编号。 每个小朋友有一个固定的传球
对象,第 i 个小朋友在接到球后会将球传给第 ai个小朋友, 并且第 i 个小朋友与第 ai个小朋
友之间的距离为 di。
一次传球接力是这样进行的:由一个小朋友发球,将球传给他的传球对象,之后接到球
的小朋友再将球传给自己的传球对象,如此传球若干次后停止。 期间,包括发球者在内,每
个小朋友至多只能拿到球一次。 一次传球接力的总距离是每次传球的距离的总和。
小朋友们想进行一次总距离最长的传球接力,现在需要你帮助他们求出满足上述要求的
传球接力的最长总距离。
【输入】
输入的第 1 行包含 1 个整数 n。
接下来的 n 行,第 i 行包含两个整数 ai 和 di,意义如题目中所述, 两个数间用一个空格
隔开。
【输出】
输出包含 1 个数, 表示传球接力总距离的最大值。
【输入输出样例 1】

pass.in pass.out
5
2 1
3 2
4 1
2 3
3 3
7

见选手目录下的 pass / pass1.in 与 pass / pass1.out
【输入输出样例 1 说明】
由第 5 个小朋友发球, 传给第 3 个小朋友,再传给第 4 个小朋友,总距离为 3+1+3=7
【数据规模与约定】
对于 50%的数据, n≤1,000
对于 100%的数据, n≤500,000, 1≤ai≤n, ai≠i, 1≤di≤10,000

分析:对图的特征一定要搞清楚,比如n个点n-1条边就是树,n个点n条边就是树套环,每个点出度为1就是很多链和环的结合体.为了走的最远,肯定要从入度为0的点出发,走到环上,顺着环走一遍.每次都模拟这样走一遍效率不高,因为一个环会被多次使用,所以可以先把环的长度给预处理出来,再把每个入度为0的点到环上的距离利用树形dp给算出来,因为最后不能回到自身嘛,枚举一下断点就可以了.

因为图可能不是连通的,会有多个环,所以要把所有的点都给处理到位.

暴力50分:

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int maxn = ; int n, head[maxn], maxx,to[maxn], nextt[maxn], w[maxn], tot = , ans;
bool vis[];
long long sum; void add(int x, int y, int z)
{
w[tot] = z;
to[tot] = y;
nextt[tot] = head[x];
head[x] = tot++;
} void dfs(int x, int d)
{
vis[x] = ;
ans = max(ans, d);
for (int i = head[x]; i; i = nextt[i])
{
int v = to[i];
if (!vis[v])
dfs(v, d + w[i]);
}
} int main()
{
scanf("%d", &n);
for (int i = ; i <= n; i++)
{
int a, d;
scanf("%d%d", &a, &d);
add(i, a, d);
}for (int i = ; i <= n; i++)
{
dfs(i, );
memset(vis, , sizeof(vis));
}
printf("%d\n", ans);return ;
}

正解:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; typedef long long ll; const int maxn = ;
ll n, a[maxn], d[maxn], du[maxn], f[maxn], sum = , ans, pre[maxn], cnt, p[maxn];
bool vis[maxn]; int main()
{
scanf("%lld", &n);
for (int i = ; i <= n; i++)
{
scanf("%lld%lld", &a[i], &d[i]);
du[a[i]]++;
}
queue <ll> q;
for (int i = ; i <= n; i++)
if (!du[i])
q.push(i);
while (!q.empty())
{
ll u = q.front();
q.pop();
ll v = a[u];
f[v] = max(f[v], f[u] + d[u]);
if (--du[v] == )
q.push(v);
}
for (int i = ; i <= n; i++)
if (du[i] && !vis[i])
{
ll k = i;
sum = ;
do
{
vis[k] = ;
p[++cnt] = k;
pre[a[k]] = d[k];
sum += d[k];
k = a[k];
} while (k != i);
for (int j = ; j <= cnt; j++)
ans = max(ans, sum + f[p[j]] - pre[p[j]]);
}
printf("%lld\n",ans); return ;
}

最新文章

  1. Java Gradle入门指南之简介、安装与任务管理
  2. 20169212《Linux内核原理与分析》第一周作业
  3. Android 开发之拦截EditText的输入内容,定制输入内容
  4. linux+apache url大小写敏感问题
  5. gcc工具链简述
  6. 找到的两个php爬虫,分享一下
  7. 【转】MVP和MVC的区别
  8. Node.js HTTP 使用详解
  9. 【转】HTML5 本地存储五种方案
  10. python序列化pickle/cPickle
  11. 【mysql】datetime时间比较
  12. django 完整日志配置
  13. Kafka+Log4j2日志
  14. flask项目结构(三)使用蓝图
  15. 【IntelliJ 】IntelliJ IDEA 2017激活码
  16. BZOJ2440 中山市选2011完全平方数(容斥原理+莫比乌斯函数)
  17. JS创建类的方法--简单易懂有实例
  18. 前端读者 | 百度前端编码规范(HTML)
  19. 刷题总结——纸带(NOIP赛前模拟)
  20. Codeforces 1163D(kmp、dp)

热门文章

  1. bzoj2679: [Usaco2012 Open]Balanced Cow Subsets(折半搜索)
  2. P3990 [SHOI2013]超级跳马
  3. 基于ASP.Net Core开发一套通用后台框架记录-(数据库设计(权限模块))
  4. python自动化测试学习笔记-6excel操作xlwt、xlrd、xlutils模块
  5. Manacher BestCoder Round #49 ($) 1002 Three Palindromes
  6. [书目20140824]触动人心:设计优秀的iPhone应用
  7. linux 常用shell命令之wc
  8. (转)中国电信友华PT921、PT921G光猫设置路由,无线WIFI设置
  9. dubbo之服务降级
  10. 探索 DWARF 调试格式信息