原题链接:蓝桥杯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、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复