zoukankan      html  css  js  c++  java
  • 【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;
    }
    

      

  • 相关阅读:
    软件测试 测试路径覆盖
    软件测试Lab Junit&Eclemma
    软件项目管理 名词解释
    使用 async/ await 进行 异步 编程
    基于任务的编程模型TAP
    异步编程(二)基于事件的异步编程模式 (EAP)
    C# 异步编程学习(一)
    C# 设计模式
    C# 读取硬盘信息 ManagementClass类
    C# show和showdialog区别
  • 原文地址:https://www.cnblogs.com/yangjiyuan/p/5699391.html
Copyright © 2011-2022 走看看