题目:
题解:
Emmm……..在用dp写了第一问之后。。我整个人都不好了,很多操作根本不能写啊,改改改。终于改成dfs版
性质题?
1、要求所有的直径都经过的边数,那么这些边一定都在同一条直径上
2、所有满足要求的边在树上都是连续的一段
3、如果以某个点为根(且不经过已知直径)的最长链 等于 这个点到已知直径某个端点距离的话,这个点之前(之后)的点一定不在合法的树链上
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#define N 200005
#define LL long long
using namespace std;
int n,i,ans,tot,nxt[N*2],point[N],v[N*2],c[N*2],d,father[N];
LL maxx,dis[N],maxn,diss[N];
int cha[N];bool vis[N];
void addline(int x,int y,int z)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;
++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; c[tot]=z;
}
void dfs(int x,int fa)
{
if (dis[x]>maxx) maxx=dis[x],d=x;
father[x]=fa;
for (int i=point[x];i;i=nxt[i])
if (v[i]!=fa)
{
dis[v[i]]=dis[x]+c[i];
dfs(v[i],x);
}
}
void Chain(int x)
{
while (x)
{
vis[x]=1;
cha[++cha[0]]=x;
x=father[x];
}
}
void dfs2(int x,int fa)
{
maxn=max(maxn,diss[x]);
for (int i=point[x];i;i=nxt[i])
if (v[i]!=fa && !vis[v[i]])
{
diss[v[i]]=diss[x]+c[i];
dfs2(v[i],x);
}
}
int main()
{
scanf("%d",&n);
for (i=1;i<n;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
addline(x,y,z);
}
dfs(1,0); memset(dis,0,sizeof(dis)); maxx=0; dfs(d,0);
printf("%lld\n",maxx);
Chain(d);
int l=cha[0],r=1;
for (i=cha[0];i>=1;i--)
{
maxn=0; dfs2(cha[i],0);
if (!maxn) continue;
if (maxn==dis[cha[i]]) l=i;
if (maxn==maxx-dis[cha[i]]) {r=i; break;}
}
printf("%d",l-r);
}