题意:
风暴斗篷现在要攻打雪漫城。雪漫城有n(n≤100000)个哨塔防守,哨塔之间有n-1条路相连,(构成一棵树)。现在预测到风暴斗篷要进攻某一条路,然后这棵树就一分为二,现在要得到分开后的最长路。
图留斯将军假定进攻所有路的概率相等,问最长路的期望*(n-1)。
分析:
这就是一个树形dp,和期望没什么关系。求的就是n-1种划分后的最长路之和。
对于一个结点x,无非要求两个东西,以它作为根的子树中的最长路,还有就是它与父亲这条路断开后,父亲那边的最长路。
代码:
比赛时的ac代码,可能很复杂,不过我懒…
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define mes(a,x,s) memset(a,x,(s)*sizeof a[0])
#define mem(a,x) memset(a,x,sizeof a)
#define ysk(x) (1<<(x))
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const int maxn=100000 ;
int n,fir[maxn+5];//ok
int nedge,nex[2*maxn+10],to[2*maxn+10],w[2*maxn+10];//ok
int a[maxn+5][3];//ok
int b[maxn+5][3];//ok
int dp[maxn+5];//ok
int up[maxn+5],down[maxn+5];//ok
int bestD[maxn+5],bestU[maxn+5];//ok
ll ans;
inline void add_edge(int x,int y,int dis)
{
to[nedge]=y;w[nedge]=dis;
nex[nedge]=fir[x];
fir[x]=nedge++;
}
void dfs(int x,int fa)
{
dp[x]=0;bestD[x]=0;
a[x][0]=a[x][1]=a[x][2]=0;
b[x][0]=b[x][1]=0;
for(int i=fir[x];~i;i=nex[i])
{
int y=to[i];if(y==fa) continue;
int dis=w[i];
dfs(y,x);
dp[x]= max(dp[x], dis+dp[y] );
bestD[x]=max(bestD[x],bestD[y]);
if(dis+dp[y] >=a[x][0] )
{
a[x][2]=a[x][1];
a[x][1]=a[x][0];
a[x][0]=dis+dp[y];
}
else if( dis+dp[y]>=a[x][1] )
{
a[x][2]=a[x][1];
a[x][1]=dis+dp[y];
}
else if(dis+dp[y]>=a[x][2] )
{
a[x][2]=dis+dp[y];
}
if(bestD[y]>=b[x][0])
{
b[x][1]=b[x][0];
b[x][0]=bestD[y];
}
else if(bestD[y]>=b[x][1])
{
b[x][1]=bestD[y];
}
}
down[x]=a[x][0]+a[x][1];
bestD[x]=max(bestD[x],down[x]);
}
void dfs2(int x,int fa)
{
for(int i=fir[x];~i;i=nex[i])
{
int y=to[i];if(y==fa) continue;
int dis=w[i];
int ret=dis+a[x][0];
if(ret==2*dis+dp[y]) ret=dis+a[x][1];
up[y]=ret;
if(ret>=a[y][0])
{
a[y][2]=a[y][1];
a[y][1]=a[y][0];
a[y][0]=ret;
}
else if(ret>=a[y][1])
{
a[y][2]=a[y][1];
a[y][1]=ret;
}
else if(ret>=a[y][2])
{
a[y][2]=ret;
}
ret=a[x][0]+a[x][1];
if(dp[y]+dis==a[x][0])
{
ret=a[x][1]+a[x][2];
}
else if(dp[y]+dis==a[x][1])
{
ret=a[x][0]+a[x][2];
}
int ret2=b[x][0];
if(bestD[y]==b[x][0] ) ret2=b[x][1];
ret=max(ret,ret2);
ret=max(ret,bestU[x]);
bestU[y]=ret;
dfs2(y,x);
}
}
int main()
{
int T,x,y,dis;scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
mes(fir,-1,n+1);
nedge=0;
for1(i,n-1)
{
scanf("%d%d%d",&x,&y,&dis);
add_edge(x,y,dis);
add_edge(y,x,dis);
}
dfs(1,-1);
up[1]=0;bestU[1]=0;
dfs2(1,-1);
ans=0;
for(int i=2;i<=n;i++)
{
ans+=max(bestD[i],bestU[i]);
}
printf("%lld\n",ans);
}
return 0;
}
/*
123312
3
1 2 4
1 3 5
332
11
1 2 1
2 3 1
2 11 1
3 8 1
8 9 1
9 10 1
3 4 1
4 5 1
4 6 1
6 7 1
*/