• 洛谷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
    ",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;
    }
    
    博主是蒟蒻,有问题请指出,谢谢!
    本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。
  • 相关阅读:
    Linux 命令
    oracle sqlplus链接和sid
    sql 应用记录
    数据库接口基础类 oracle,sql server
    oracle 触发器
    js json -> <-object
    Docker学习总结(三)--常用命令
    MySQL之binlog日志
    Redis学习总结(九)-- Redis常用技巧
    Redis学习总结(八)--Redis云平台
  • 原文地址:https://www.cnblogs.com/xzz_233/p/7436647.html
Copyright © 2020-2023  润新知