大臣的旅费 四届c++ A T10
题意:
给定一棵树,求直径
思考:
方法一
BFS。先任取一点,跑一遍bfs找到距离最大的点,再对距离最大的那个点作为起点,跑一遍bfs,就能找到直径了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| #include <iostream> #include <vector> #include <cstring> #include <algorithm> #include <queue> #include <deque>
using namespace std; const int N=1e5+10; typedef pair<int,int> PII; typedef long long LL; vector<PII> mp[N]; int n,p,q,d,dis[N]; bool st[N]; LL ans,idx; void bfs(int u){ memset(dis,0x3f,sizeof dis); memset(st,0,sizeof st); queue<int> qu; st[u]= true; qu.push(u); dis[u]=0; ans=dis[u]; idx=u; while(!qu.empty()){ int tp=qu.front(); qu.pop(); for(auto pi:mp[tp]){ if(st[pi.second]) continue; dis[pi.second]=dis[tp]+pi.first; if(dis[pi.second]>ans){ idx=pi.second; ans=dis[pi.second]; } qu.push(pi.second); st[pi.second]=true; } } } int main(){ cin>>n; for(int i=0;i<n-1;i++){ scanf("%d%d%d",&p,&q,&d); mp[p].push_back({d,q}); mp[q].push_back({d,p}); } bfs(1); bfs(idx); cout<<ans*10+(ans+1)*ans/2; return 0; }
|
技巧总结:以前蓝桥杯的题是真的简单(还是最后一题hh)
方法二
树形dp。从任意结点开始,找到每个结点且经过该节点向下走的最大长度d1和次大长度d2,则经过该节点的最大长度是d1 + d2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #include <iostream> #include <vector> #include <cstring> #include <algorithm> #include <queue> #include <deque>
using namespace std; const int N=1e5+10; typedef pair<int,int> PII; typedef long long LL; vector<PII> mp[N]; LL n,p,q,d,dis[N]; bool st[N]; LL ans,idx; void dp(int u){ st[u]= true; for(auto tp:mp[u]){ if(st[tp.second]) continue; dp(tp.second); ans=max(ans,dis[u]+dis[tp.second]+tp.first); dis[u] = max(dis[u],dis[tp.second]+tp.first); } } int main(){ cin>>n; for(int i=0;i<n-1;i++){ scanf("%lld%lld%lld",&p,&q,&d); mp[p].push_back({d,q}); mp[q].push_back({d,p}); } dp(1); cout<<ans*10+(ans+1)*ans/2; return 0; }
|