• 【bzoj2282】[Sdoi2011]消防


    两次bfs可得直径,答案一定不会小于所有点到直径的距离最大值,只要把直径上的边权设为0,任选直径上一点bfs可得将最大值作为二分下界,二分直径左右端点的舍弃部分

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    using namespace std;
     
    #define N 300010
     
    struct edge
    {
        int to,next,w;
    }e[N<<1];
    int head[N<<1];
    int cnt;
     
    int n,s;
     
    int rt,x,y,z;
     
    int maxn,top,D;
     
    int st[N],from[N],mark[N],dis[N];//,q[N];
     
    queue<int>q;
     
    void link(int x,int y,int z)
    {
        e[++cnt]=(edge){y,head[x],z};
        head[x]=cnt;
    }
     
    void bfs(int x)
    {
        for (int i=1;i<=n;i++)
            dis[i]=-1;
        q.push(x);
        dis[x]=0;
        while (!q.empty())
        {
            int now=q.front();
            q.pop();
            for (int i=head[now];i;i=e[i].next)
            {
                int t=e[i].to;
                if (dis[t]==-1)
                {
                    from[t]=now;
                    if (mark[t])
                        dis[t]=dis[now];
                    else
                        dis[t]=dis[now]+e[i].w;
                    q.push(t);
                }
            }
        }
    }
          
    bool work(int d)
    {
        int l=1,r=top;
        while (st[1]-st[l+1]<=d && l<=top)
            l++;
        while (st[r-1]<=d && r>=1)
            r--;
        return st[l]-st[r]<=s;
    }
    int main()
    {
        scanf("%d%d",&n,&s);
        for (int i=1;i<n;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            link(x,y,z);
            link(y,x,z);
        }
        bfs(1);
        for (int i=1;i<=n;i++)
            if (dis[rt]<dis[i])
                rt=i;
        bfs(rt);
        for (int i=1;i<=n;i++)
            if (dis[x]<dis[i])
                x=i;
        D=dis[x]; 
        st[++top]=dis[x];
        mark[x]=1;
        while (x!=rt)
        {
            st[++top]=dis[from[x]];
            x=from[x];
            mark[x]=1;
        }
        bfs(x);
        int l=0,r=D;
        for(int i=1;i<=n;i++)
            l=max(l,dis[i]);
        if (s<D)
            while (l<=r)
            {
                int mid=(l+r)>>1;
                if (work(mid))
                    r=mid-1;
                else
                    l=mid+1;
            }
        printf("%d
    ",l);
        return 0;
    }
    

      

  • 相关阅读:
    Linux模拟网络延迟、丢包等
    TestLink汉化操作
    onems设备管理系统(TR-069和OMA)
    Installation Guide Ubuntu 16.04
    Configure GenieACS
    Linux下的tar压缩解压缩命令详解
    genieacs Installation on Ubuntu14.04
    Pyqt中富文本编辑器
    安装MongoDB
    到底什么是贝叶斯?
  • 原文地址:https://www.cnblogs.com/yangjiyuan/p/5699391.html
Copyright © 2020-2023  润新知