bzoj1999

这道题真的做得头皮发麻

题解。。。lyd书上。。。

头皮发麻

 

。。。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

const int maxn=600000+10;
const int nil=0x3f3f3f3f;

struct my{
       int next;
       int w;
       int v;
};

my bian[maxn*2];
queue<int>Q;
int adj[maxn],fa,n,pre[maxn],d[maxn],p,path[maxn],top,sum1[maxn],sum2[maxn],q[maxn];
bool c[maxn];

void myinsert(int u,int v,int w){
     bian[++fa].v=v;
     bian[fa].next=adj[u];
     bian[fa].w=w;
     adj[u]=fa;
}

int bfs(int x){
    while(!Q.empty()) Q.pop();
    memset(d,0x3f,sizeof(d));
    d[x]=0;
    pre[x]=0;
    Q.push(x);
    while(!Q.empty()){
        int u=Q.front();Q.pop();
        for (int i=adj[u];i;i=bian[i].next){
                int v=bian[i].v;
            if(d[v]==nil){
                d[v]=d[u]+bian[i].w;
                pre[v]=i;
                Q.push(v);
            }
        }
    }
    int p=1,y=1;
    for (;p<=n;p++) if(d[y]<d[p]) y=p;
    return y;
}

void dp1(int x,int f){
     for (int i=adj[x];i;i=bian[i].next){
        int v=bian[i].v;
        if(c[v]&&v!=f){
            sum1[v]=sum1[x]+bian[i].w;
            dp1(v,x);
        }
     }
}

void dp2(int x,int f){
     for (int i=adj[x];i;i=bian[i].next){
        int v=bian[i].v;
        if(c[v]&&v!=f){
            sum2[v]=sum2[x]+bian[i].w;
            dp2(v,x);
        }
     }
}

void get(){
     p=bfs(1);
     p=bfs(p);
}

void lu(){
     for (;pre[p];p=bian[pre[p]^1].v) {//可以记录路径,但是一直没搞懂是怎么回事,可能是我太弱吧,记住好了
           // printf("%d %d ",bian[pre[p]].v,bian[pre[p]^1].v);
           if(!c[bian[pre[p]].v]) path[++top]=bian[pre[p]].v;
           if(!c[bian[pre[p]^1].v]) path[++top]=bian[pre[p]^1].v;
            c[bian[pre[p]].v]=true;
            c[bian[pre[p]^1].v]=true;
     }
}

void dfs(int x){
     c[x]=1;
     for (int i=adj[x];i;i=bian[i].next){
            int v=bian[i].v;
            if(c[v]) continue;
            //printf("%d %d\n",x,v);
            dfs(v);
            d[x]=max(d[x],d[v]+bian[i].w);
     }
}

int main(){
    //freopen("1999.in","r",stdin);
   // freopen("1999.out","w",stdout);
    fa=1;
    int u,v,w;
    int s;
    scanf("%d%d",&n,&s);
    for (int i=1;i<n;i++){
        scanf("%d%d%d",&u,&v,&w);
        myinsert(u,v,w);
        myinsert(v,u,w);
    }
    get();
    lu();
    //for (int i=1;i<=top;i++) printf("%d ",path[i]);
    dp1(path[1],path[1]);
    dp2(path[top],path[top]);
    memset(d,0,sizeof(d));
    for (int i=1;i<=top;i++)
                dfs(path[i]);
    int ans=nil;
    int pp=0;
    for (int i=1;i<=top;i++){
        pp=max(pp,d[path[i]]);
    }
    int ppl=0;
    int i=1,j=1;
    for (;i<=top,j<=top;i++){
        ppl=0;
        while(j<=top&&abs(sum1[path[j]]-sum1[path[i]])<=s) j++;
        ppl=max(ppl,pp);
        ppl=max(ppl,sum1[path[i]]);
        ppl=max(ppl,sum2[path[j]]);
        ans=min(ans,ppl);
    }
    printf("%d\n",ans);
return 0;
}

 还是画图理解一下

设路径p为最长的不经直径路径,那么p必小于w(u,v),所以v之后路径都比p长

所以了嘛,答案要么就是p,要么就在直径上

对,没毛病

丝毫没毛病

posted @ 2018-07-26 11:34  lmjer  阅读(159)  评论(0编辑  收藏  举报