大臣的旅费

原题链接

思路分析:树的直径
根据在走第 x x x千米到第 x + 1 x+1 x+1千米这一千米中 x x x是整数)这句话,很容易推导出这是一个等差数列。根据求和公式就可以得到若走 x x x千米,则旅费满足 ( 21 + x ) ∗ x 2 \frac{(21+x)*x}{2} 2(21+x)x。由题意可知,所求路径为树的直径,利用树形 d p dp dp求得树的直径,代入公式求解即可。
求解方法和证明过程可以参考这里。

C o d e : Code: Code:

注意 a n s = m a x ( a n s , d p [ x ] + d p [ j ] + t r e e [ i ] . c o s t ) ans=max(ans,dp[x]+dp[j]+tree[i].cost) ans=max(ans,dp[x]+dp[j]+tree[i].cost)
d p [ x ] = m a x ( d p [ x ] , d p [ j ] + t r e e [ i ] . c o s t ) dp[x]=max(dp[x],dp[j]+tree[i].cost) dp[x]=max(dp[x],dp[j]+tree[i].cost)不能调换位置,首先要明确 d p [ x ] dp[x] dp[x]的含义是以 x x x为根,所能到达最远的节点的距离,且设根节点 x x x有左节点 u u u与右节点 v v v u → x → v u\rightarrow{x}\rightarrow{v} uxv为树的直径,所以在运行到 a n s = m a x ( a n s , d p [ x ] + d p [ j ] + t r e e [ i ] . c o s t ) ans=max(ans,dp[x]+dp[j]+tree[i].cost) ans=max(ans,dp[x]+dp[j]+tree[i].cost)时, d p [ x ] dp[x] dp[x]仅仅代表 u → x u\rightarrow{x} ux这一部分,缺少直径中的 x → v x\rightarrow{v} xv。运行结束后,跟新 d p [ x ] dp[x] dp[x]的值。如果先运行 d p [ x ] = m a x ( d p [ x ] , d p [ j ] + t r e e [ i ] . c o s t ) dp[x]=max(dp[x],dp[j]+tree[i].cost) dp[x]=max(dp[x],dp[j]+tree[i].cost),会造成直径的计算错误。

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include 
using namespace std;
#define MaxN 100010
//#define MOD 998244353
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define endl '\n'
#define LL long long
#define PII pair
#define rint register int 
#define ULL unsigned long long
const int MOD=1e9+7;
//int days[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
//int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
template<class T> inline void read(T& x){
    x=0;int f=0;char ch=getchar();
    while( !isdigit(ch) ) f|=( ch == '-' ) , ch=getchar();
    while( isdigit(ch) )  x = ( x<<1 ) + ( x<<3 ) + ( ch^48 ) , ch=getchar();
    x = f ? -x : x;
}
template<class T> inline void print(T x){
    if ( x < 0 ) { putchar('-'); x = -x; }
    if ( x >= 10 ) print( x / 10 );
    putchar(x % 10 + '0');
}
struct Node{
    int to,cost,Next;
}tree[MaxN*2];
int head[MaxN*2],dp[MaxN],cnt,ans=-INF;
bool flag[MaxN];
void Add(int u,int v,int w){
    tree[cnt].to=v;
    tree[cnt].cost=w;
    tree[cnt].Next=head[u];
    head[u]=cnt++;
}
void Dfs(int x){
    flag[x]=true;
    for(int i=head[x]; ~i; i=tree[i].Next){
        int j=tree[i].to;
        if( !flag[j] ){
            Dfs(j);
            ans=max(ans,dp[x]+dp[j]+tree[i].cost);
            dp[x]=max(dp[x],dp[j]+tree[i].cost);
        }
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    memset(head,-1,sizeof(head));
    int n;
    cin>>n;
    for(int i=1; i<n; i++){
        int u,v,w;
        cin>>u>>v>>w;
        Add(u,v,w);
        Add(v,u,w);
    }
    Dfs(1);
    cout<<1ll*(21+ans)*ans/2<<endl;
    return 0; 
} 

你可能感兴趣的:(题解)