原题链接:蓝桥杯2013年第四届真题-大臣的旅费
解题思路:
这道题难点就是不知道n的最大值。
由题可知,有n-1条边n个结点且连通,那么显然这个图是一棵树。
定义d[i]=从节点i出发往下走的最长路径,则状态转移方程:
d[i]=max{ d[i], w[i][j]+d[j] }, j属于{i的儿子}
在求解d[i]的过程中,我们可以顺便保存一下 w[i][j]+d[j] 的第二大值cmax。
那么答案就是 {d[i]+cmax},i属于{所有结点}。
时间复杂度O(T)=O(nlogn), 本题AC耗时:30ms(使用自己写的hashmap就是20ms)当然这个OJ时间不准;
注意事项:
参考代码:
#include <vector>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#define _for(i,a,b) for(int i=a;i<b;i++)
#define RI(a) scanf("%d",&a)
using namespace std;
typedef long long LL;
int d[111111],n,vis[111111],ans=0;
vector<int> G[111111];
map<pair<int,int>,int> W;
int dfs(int i){
if(d[i])return d[i];
vis[i]=1;
int m1=0,m2=0,len=G[i].size();
_for(k,0,len)if(!vis[G[i][k]]){
vis[G[i][k]]=1;
pair<int,int> pr(i>G[i][k]?i:G[i][k],i>G[i][k]?G[i][k]:i);
int t=W[pr]+dfs(G[i][k]);
if(t>m2)if((m2=t)>m1)swap(m1,m2);
ans=max(ans,m1+m2);
}
return d[i]=m1;
}
int main(){
RI(n);
_for(i,1,n){
int a,b,c;
RI(a);RI(b);RI(c);
G[a].push_back(b);
G[b].push_back(a);
pair<int,int> pr(a>b?a:b,a>b?b:a);
W[pr]=c;
}
dfs(1);
cout<<(LL)(ans+1)*ans/2+ans*10<<endl;
}0.0分
1 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复