zoukankan      html  css  js  c++  java
  • 【SDOI2011 第2轮 DAY1】消防 树上问题+二分+贪心

    问题:
      某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000)。
      这个国家的人对火焰有超越宇宙的热情,所以这个国家最兴旺的行业是消防业。由于政府对国民的热情忍无可忍(大量的消防经费开销)可是却又无可奈何(总统竞选的国民支持率),所以只能想尽方法提高消防能力。
      现在这个国家的经费足以在一条边长度和不超过s的路径(两端都是城市)上建立消防枢纽,为了尽量提高枢纽的利用率,要求其他所有城市到这条路径的距离的最大值最小。
      你受命监管这个项目,你当然需要知道应该把枢纽建立在什么位置上。

    输入格式

    输入包含n行:
    第1行,两个正整数n和s,中间用一个空格隔开。其中n为城市的个数,s为路径长度的上界。设结点编号以此为1,2,……,n。
      从第2行到第n行,每行给出3个用空格隔开的正整数,依次表示每一条边的两个端点编号和长度。例如,“2 4 7”表示连接结点2与4的边的长度为7。

    输出格式

       输出包含一个非负整数,即所有城市到选择的路径的最大值,当然这个最大值必须是所有方案中最小的。

    样例输入

    【样例输入1】
    5 2
    1 2 5
    2 3 2
    2 4 4
    2 5 3
     
    【样例输入2】
    8 6
    1 3 2
    2 3 2 
    3 4 6
    4 5 3
    4 6 4
    4 7 2
    7 8 3 

    样例输出

    【样例输出1】
    5

    【样例输出2】
    5

    提示

    【数据规模和约定】
    对于20%的数据,n<=300。
    对于50%的数据,n<=3000。
    对于100%的数据,n<=300000,边长小等于1000。

    解:

    这题有一个明显的二分信号 

    然后关键是怎么贪心验证答案

    注意到: 我们有

    距离树上的任意一个点的最远的点距离最大的点一定是树的端点 (树的直径找法)

    然后就是路径选取的问题 

    画下图可知 这条路径一定在树 的直径上 否则距离最大不是最优 的解

    所以我们两次BFS 求出树 的 直径 然后二分答案 在直径上选取合适的路径 (二分答案的下界是 树的任意一点到直径的距离    上界是直径的长度)

    code:

    //
    #include<bits/stdc++.h>
    using namespace std;
    int n,ss;
    #define maxnn 700000
    int las[maxnn],nex[maxnn],en[maxnn],le[maxnn],tot;
    int mark[maxnn];
    int b[maxnn];
    int ccc[maxnn];
    int r,l;
    void add(int a,int b,int c) {
        en[++tot]=b;
        nex[tot]=las[a];
        las[a]=tot;
        le[tot]=c;
    }
    queue <int > Q;
    int bfs(int v) {
        memset(ccc,0,sizeof(ccc));
        memset(mark,0,sizeof(mark));
        int male=0;
        int ans=0;
        mark[v]=1;
        int lle=0;
        Q.push(v);
        while(Q.size()) {
            int s=Q.front();
            Q.pop();
                for(int i=las[s]; i; i=nex[i]) {
                int u=en[i];
                if(!mark[u]) {
                    Q.push(u);
                    ccc[u]=ccc[s]+le[i];
                    mark[u]=1;
                    if(male<ccc[s]+le[i]) {
                        male=max(male,ccc[s]+le[i]);
                        ans=u;
                    }
                }
            }
        }
        return ans;
    }
    void dfs(int s1,int s2,int v,int s)
    {
        l=max(l,s);
        for(int i=las[v];i;i=nex[i])
        {
            int u=en[i];
            if(u!=s1&&u!=s2)
            {
                dfs(v,v,u,s+le[i]);
            }
            
        }
    }
    void ddfs(int fa,int x,int y ,int t ,int s) {
        if(x==y)
        {
            b[0]=t;
            b[t]=s;
            r=s;
            return ;
        }
        for(int i=las[x];i;i=nex[i])
        {
                int v=en[i];
                if(fa!=v)
                {
                ddfs(x,v,y,t+1,s+le[i]);
                if(b[0])
                {
                    b[t]=s;
                    dfs(fa,en[i],x,0);//直径的前缀和
                    return ;
                }
            }
        }
    }
    bool check(int v)
    {
        int i=1,j=1;
        for(i=1;i<=b[0];i++)
        {
            if(b[i]>v) break;
        }
        i--;
        for(j=i;j<=b[0];j++)
        {
            if(b[j]-b[i]>ss) break;
        }
        j--;
        return b[b[0]]-b[j]<=v;
        
    }
    int main() {
        cin>>n>>ss;
        int x,y,z;
        for(int i=1; i<n; i++) {
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
            add(y,x,z);
        }
        int ll =bfs(1);
        int rr=bfs(ll);
        ddfs(0,ll,rr,1,0);
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(check(mid)) r=mid-1;
            else
            l=mid+1;
        }
        cout<<l;
    
    }
    刀剑映出了战士的心。而我的心,漆黑且残破
  • 相关阅读:
    逻辑智力题【更新中】
    每天进步一点点_抽奖程序
    GDC2016【For Honor-荣耀战魂】的次世代动画技术
    GDC2016【彩虹六号:围攻 】使丰富的“突破”成为可能的破坏系统
    GDC2016 【巫师3 狂猎】的游戏事件工作流
    GDC 2016 神秘海域4中使用Substance制作Texture
    GDC2016【全境封锁(Tom Clancy's The Division)】对为何对应Eye Tracked System,以及各种优点的演讲报告
    【FFXV】中物理模拟的结构以及游戏业界的乐趣
    龙珠 超宇宙 [Dragon Ball Xenoverse]
    如龙0
  • 原文地址:https://www.cnblogs.com/OIEREDSION/p/11370601.html
Copyright © 2011-2022 走看看