洛谷1099 树网的核
原题链接
交题记录
22:32 80'
被某人Hack了。服气。。。
22:45 AC
题解
两种做法。
1、floyd暴力搞,不再多说。
2、树的直径
先随便求一条直径,这个就是两遍dfs的事。端点为a,b。
显然那条路径应该越长越好。在路径上枚举一个起始点c,贪心出终点d再算ecc。
ecc怎么求???
(ecc=max(dist(a,c),dist(b,d)))
利用一条性质:对于直径中的任意一点,其距离树中其他点的最远距离不超过该点到达直径端点的距离。
然而。。。如果出现了(a=c,b=d)就会gg(这正是hack我的人干的233),这时直径就是最优解爆算即可。
剩下的。。。都是dfs的事了吧
Code
// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<cstdlib>
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
#define t (dis[i])
typedef long long ll;
il int gi(){
rg int x=0,f=1;rg char ch=getchar();
while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int maxn=302,maxm=maxn<<1;
int fir[maxn],nxt[maxm],w[maxm],dis[maxm],fa[maxn],l[maxn],id,n,s;
bool yes[maxn];
il vd add(int a,int b,int c){nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c;}
int ans,anslen;
il vd dfs(int now,int len,int fa=-1){
if(len>anslen)anslen=len,ans=now;
erep(i,now)if(t^fa)dfs(t,len+w[i],now);
}
il vd Dfs(int now,int len){
if(len>anslen)anslen=len,ans=now;
erep(i,now)if(t^fa[now])fa[t]=now,l[t]=w[i],Dfs(t,len+w[i]);
}
il vd dFs(int now,int len,int fa=-1){
if(!yes[now]&&len>anslen)anslen=len;
erep(i,now)if((t^fa)&&!yes[t])dFs(t,len+w[i],now);
}
int main(){
n=gi(),s=gi();
{
int a,b,c;
rep(i,2,n)a=gi(),b=gi(),c=gi(),add(a,b,c),add(b,a,c);
}
dfs(1,0);int a=ans;
anslen=0;
Dfs(a,0);int b=ans;
ans=1e9;
int sum=0;
for(rg int i=b;i!=a;i=fa[i]){
int k=i,tot=0,res=sum;
while(k!=a&&tot+l[k]<=s)tot+=l[k],k=fa[k];
if(i==b&&k==a){
for(rg int j=b;j!=a;j=fa[j])yes[j]=1;yes[a]=1;
anslen=0;
for(rg int j=b;j!=a;j=fa[j])dFs(j,0);dFs(a,0);
printf("%d
",anslen);
return 0;
}
int sum2=0;
for(rg int j=k;j!=a;j=fa[j])sum2+=l[j];
res=max(res,sum2);
ans=min(ans,res);
sum+=l[i];
}ans=min(ans,sum);
printf("%d
",ans);
return 0;
}