zoukankan      html  css  js  c++  java
  • 【Luogu】P2491消防(单调队列)

      题目链接

      首先可以想到路径一定是在直径上的。

      然后对每个点dfs出不经过直径的以它开始的路径最大长度,记为dis

      然后就可以求出直径之后枚举左右端点,设左端点l右端点r,直径上点距离直径上起点的距离用sum[]表示

      则此时的$ans=max(max(sum[l],sum[End]-sum[r]),max(dis[i])l<=i<=r))$

      右面那个玩意可以单调队列维护。

      (然后我单调队列打反了变成维护最小值,GG。)

      

    #include<cstdio>
    #include<algorithm>
    #include<cctype>
    #include<cstring>
    #include<cstdlib>
    #define maxn 600030
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    struct Edge{
        int next,to,val;
    }edge[maxn*2];
    int head[maxn],num;
    inline void add(int from,int to,int val){
        edge[++num]=(Edge){head[from],to,val};
        head[from]=num;
    }
    
    int dis[maxn];
    bool vis[maxn];
    int stack[maxn],top;
    int sum[maxn];
    int End;
    int n,m;
    
    void find(int x,int fa){
        for(int i=head[x];i;i=edge[i].next){
            int to=edge[i].to;
            if(to==fa)    continue;
            dis[to]=dis[x]+edge[i].val;
            find(to,x);
            if(dis[End]<dis[to])    End=to;
        }
    }
    
    void record(int x,int fa){
        if(x==End){
            stack[++top]=x;
            vis[x]=1;
            return;
        }
        for(int i=head[x];i;i=edge[i].next){
            int to=edge[i].to;
            if(to==fa)    continue;
            record(to,x);
            if(vis[to]){
                stack[++top]=x;
                sum[top]=sum[top-1]+edge[i].val;
                vis[x]=1;
            }
        }
    }
    
    void calc(){
        find(1,1);
        dis[End]=1;
        int Start=End;
        find(End,End);
        record(Start,Start);
    }
    
    int dfs(int x,int fa){
        int ans=0;
        for(int i=head[x];i;i=edge[i].next){
            int to=edge[i].to;
            if(to==fa||vis[to]==1)    continue;
            ans=max(ans,dfs(to,x)+edge[i].val);
        }
        return ans;
    }
    
    int que[maxn],h=1,t;
    
    
    int main(){
        n=read(),m=read();
        for(int i=1;i<n;++i){
            int from=read(),to=read(),val=read();
            add(from,to,val);
            add(to,from,val);
        }
        calc();
        for(int i=1;i<=top;++i)    dis[i]=dfs(stack[i],stack[i]);
        int rig=1;int ans=0x7fffffff;
        for(int i=1;i<=top;++i){
            int le=sum[i];
            while(sum[rig+1]-sum[i]<=m&&rig<top){
                rig++;
                while(h<=t&&dis[que[t]]<=dis[rig])    t--;
                que[++t]=rig;
                while(h<=t&&que[h]<i)    h++;
                int now=max(le,max(sum[top]-sum[rig],dis[que[h]]));
                ans=min(ans,now);
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    备份一些觉得很有用的网站或者资料或者新的一些属性方法技术
    ios下iphone的plus下
    四川大学2008年数学分析考研试题
    四川大学2007年数学分析考研试题
    四川大学2006年数学分析考研试题
    四川大学2005年数学分析考研试题
    四川大学2003年数学分析考研试题
    四川大学2002年数学分析考研试题
    四川大学2001年数学分析考研试题
    四川大学2000年数学分析考研试题
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8857949.html
Copyright © 2011-2022 走看看