传送门:>HERE<
题意:给出一棵树(带权),要从一个节点C先走到距离它近的一个节点B,再走到A,要求最坏情况下的总路程(即最长)。
解题思路:
乍一看,A,B,C都没给出,这怎么求?
不妨设距离C较近的点位A。
分析发现,无论怎样,A~B是一定要走的。那么如何能让树上任意两点间距离最大呢?不难发现A,B就是该树直径的两个端点。那么只要两遍BFS就好了。
那么如何让A~C的路程最长呢?注意到A到C相较A到B是较短的。所以好像不怎么好求……但是可以枚举——枚举每个点作为C到A和B的距离,求出较小的那个,并且打擂得到最大值。
Code
/*By QiXingzhi*/ #include <cstdio> #include <queue> #include <iostream> #include <string> #include <cstring> #include <algorithm> #define r read() #define Max(a,b) (((a)>(b)) ? (a) : (b)) #define Min(a,b) (((a)<(b)) ? (a) : (b)) using namespace std; typedef long long ll; #define int ll const int N = 200010; const int INF = 1061109567; inline int read(){ int x = 0; int w = 1; register int c = getchar(); while(c ^ '-' && (c < '0' || c > '9')) c = getchar(); if(c == '-') w = -1, c = getchar(); while(c >= '0' && c <= '9') x = (x << 3) +(x << 1) + c - '0', c = getchar(); return x * w; } struct Edge{ int to,cost; }; int n,m,x,y,z,A,B,ans,ans2; int d[N], d2[N], vis[N]; vector <Edge> G[N]; queue <int> q; inline void AddEdge(int u, int v, int w){ Edge e; e.to = v; e.cost = w; G[u].push_back(e); } inline void BFS(int s){ while(!q.empty()) q.pop(); q.push(s); d[s] = 0; vis[s] = 1; int cur,sz,v; while(!q.empty()){ cur = q.front(); q.pop(); sz = G[cur].size(); for(int i = 0; i < sz; ++i){ v = G[cur][i].to; if(!vis[v]){ vis[v] = 1; d[v] = d[cur] + G[cur][i].cost; q.push(v); } } } } inline void BFS2(int s){ while(!q.empty()) q.pop(); q.push(s); d2[s] = 0; vis[s] = 1; int cur,sz,v; while(!q.empty()){ cur = q.front(); q.pop(); sz = G[cur].size(); for(int i = 0; i < sz; ++i){ v = G[cur][i].to; if(!vis[v]){ d2[v] = d2[cur] + G[cur][i].cost; vis[v] = 1; q.push(v); } } } } main(){ n = r, m = r; for(int i = 1; i <= m; ++i){ x = r, y = r, z = r; AddEdge(x, y, z); AddEdge(y, x, z); } BFS(1); int __max = -100; for(int i = 1; i <= n; ++i){ if(d[i] > __max){ __max = d[i]; A = i; } } ans = __max; memset(vis,0,sizeof(vis)); BFS(A); __max = -100; for(int i = 1; i <= n; ++i){ if(d[i] > __max){ __max = d[i]; B = i; } } ans = __max; memset(vis,0,sizeof(vis)); BFS2(B); for(int i = 1; i <= n; ++i) ans2 = Max(ans2, Min(d[i], d2[i])); printf("%lld", ans+ans2); return 0; }