洛谷1099 树网的核

洛谷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\n",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\n",ans);
    return 0;
}
posted @ 2017-08-26 22:57  菜狗xzz  阅读(134)  评论(0编辑  收藏  举报