• NOI2013 快餐店


    http://uoj.ac/problem/126

    总的来说,还是很容易想的,就是有点恶心。

    首先,很明显只有一个环。

    我们先找出这个环,给各棵树编号id[i],然后各棵树分别以环上的点为根,求出每个点的深度dep[i],根节点st[i],最深的孩子的深度furthestson[i]和不进入子树最远的点距离f[i],这些都比较好求。

    我们分2种情况讨论:

    (1)快餐店在环上

           将环上的点以furthestson[i]为权值,等价于快餐店到点的最短距离再加上点的权值的最大值最小。

           其实我们可以将这个环看成一个正圆,过快餐店的一条直径将这个圆分成2部分,快餐店顺时针到左边的点,逆时针到右边的点,我们分别将左边的点和右边的点分别放在2个单调队列中。

    当我们逆时针旋转这条直径的时候,左右两边是单调的,可以用单调队列,然后更新答案即可。

    (2)快餐店在树上

    我们在(1)中顺便记录一下第i棵树不进入本树可以到达的最远距离h[i]

    我们枚举树边(u,v),不失一般性,dep[u]<dep[v],且其长度为l。

    那么这条路径v那一端最远可以到的距离为furthestson[v],u那一端最远可以到的距离为max(f[v]-l,dep[u]+h[id[st[u]]])。

    然后更新答案即可。

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<fstream>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<vector>
    #include<functional>
    #include<deque>
    #include<cctype>
    #include<climits>
    #include<complex>
    //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
     
    using namespace std;
    
    typedef long long LL;
    typedef double DB;
    typedef pair<int,int> PII;
    typedef complex<DB> CP;
    
    #define mmst(a,v) memset(a,v,sizeof(a))
    #define mmcy(a,b) memcpy(a,b,sizeof(a))
    #define re(i,a,b)  for(i=a;i<=b;i++)
    #define red(i,a,b) for(i=a;i>=b;i--)
    #define fi first
    #define se second
    #define m_p(a,b) make_pair(a,b)
    #define SF scanf
    #define PF printf
    #define two(k) (1<<(k))
    
    template<class T>inline T sqr(T x){return x*x;}
    template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
    template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}
    
    const DB EPS=1e-9;
    inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
    const DB Pi=acos(-1.0);
    
    inline void clear(vector<int> *A,int a,int b){int i,j;A->clear();re(i,0,a)re(j,0,b)A[i].push_back(0);}
    
    inline int gint()
      {
            int res=0;bool neg=0;char z;
            for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
            if(z==EOF)return 0;
            if(z=='-'){neg=1;z=getchar();}
            for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
            return (neg)?-res:res; 
        }
    inline LL gll()
      {
          LL res=0;bool neg=0;char z;
            for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
            if(z==EOF)return 0;
            if(z=='-'){neg=1;z=getchar();}
            for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
            return (neg)?-res:res; 
        }
    
    const int maxN=100000;
    
    int N;
    int now,first[maxN+100];
    struct Tedge{int u,v,next,dis;}edge[2*maxN+100];
    DB ans;
    
    inline void addedge(int u,int v,int dis)
      {
          now++;
          edge[now].u=u;
          edge[now].v=v;
          edge[now].dis=dis;
          edge[now].next=first[u];
          first[u]=now;
      }
    
    #define next(i) (i%cnt+1)
    #define qian(i) ((i-2+cnt)%cnt+1)
    int cnt,root[maxN+10];
    LL lon[maxN+10];
    int id[maxN+100];
    
    int vis[maxN+10];
    int fa[maxN+100];
    int sta[maxN+10],last[maxN+10],top;
    inline void DFS()
      {
          mmst(vis,0);
          mmst(fa,0);
          vis[sta[top=1]=1]=1;
          last[1]=first[1];
          while(top>=1)
            {
                int u=sta[top],i=last[top],v;
                for(v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)
                  {
                      if(!vis[v])
                        {
                            last[top]=edge[i].next;
                            vis[sta[++top]=v]=1;
                            last[top]=first[v];
                            fa[v]=u;
                            break;
                        }
                      if(vis[v] && v!=fa[u])
                        {
                          while(sta[top]!=v)root[++cnt]=sta[top--];
                        root[++cnt]=v;
                        return;
                      }
                  }
                if(i==-1)top--;
            }
      }
    
    inline void findround()
      {
          int i,j;
          DFS();
          re(i,1,cnt)
            {
                id[root[i]]=i;
                int v,dis;
                for(j=first[root[i]],v=edge[j].v,dis=edge[j].dis;j!=-1;j=edge[j].next,v=edge[j].v,dis=edge[j].dis)
                  if(v==root[next(i)]){lon[i]=LL(dis);break;}
                }
      }
    
    int head,tail,que[maxN+100];
    
    LL dep[maxN+100],furthestson[maxN+100],f[maxN+100];
    int st[maxN+100];
    inline void solve1(int rt)
      {
          int i,j;
          vis[que[head=tail=1]=rt]=1;
          dep[rt]=0;
          fa[rt]=0;
          while(head<=tail)
            {
                int u=que[head++],v,dis;
                for(i=first[u],v=edge[i].v,dis=edge[i].dis;i!=-1;i=edge[i].next,v=edge[i].v,dis=edge[i].dis)
                  if(id[v]==0 && !vis[v])
                    {
                        fa[v]=u;
                        vis[que[++tail]=v]=1;
                        dep[v]=dep[u]+LL(dis);
                    }
            }
          red(j,tail,1)
            {
                int u=que[j],v,dis;
                furthestson[u]=0;
                for(i=first[u],v=edge[i].v,dis=edge[i].dis;i!=-1;i=edge[i].next,v=edge[i].v,dis=edge[i].dis)
                      if(id[v]==0 && v!=fa[u])
                          upmax(furthestson[u],furthestson[v]+LL(dis));
            }
          f[rt]=0;
          re(j,1,tail)
            {
                int u=que[j],v,dis;LL maxv1=0,maxv2=0;int hea=-1;
                for(i=first[u],v=edge[i].v,dis=edge[i].dis;i!=-1;i=edge[i].next,v=edge[i].v,dis=edge[i].dis)
                  if(id[v]==0 && v!=fa[u])
                    {
                      if(furthestson[v]+LL(dis)>maxv1)
                        maxv2=maxv1,maxv1=furthestson[v]+LL(dis),hea=v;
                      else
                        if(furthestson[v]+LL(dis)>maxv2)
                          maxv2=furthestson[v]+LL(dis);
                    }
                for(i=first[u],v=edge[i].v,dis=edge[i].dis;i!=-1;i=edge[i].next,v=edge[i].v,dis=edge[i].dis)
                  if(id[v]==0 && v!=fa[u])
                    {
                      if(v!=hea)
                        f[v]=LL(dis)+max(f[u],maxv1);
                      else
                        f[v]=LL(dis)+max(f[u],maxv2);
                    }
            }
          re(i,1,tail)st[que[i]]=rt;
      }
    
    DB h[maxN+100];
    
    struct Tque
      {
          int head,tail;
          DB add,que[2*maxN+100],idx[2*maxN+10];////////////////注意,要2倍空间!!!!!!!!!!!!!!!!!!!!
          inline void clear(){head=1;tail=0;add=0.0;}
          inline void insert(int id,DB v)
            {
                ++tail;que[tail]=v-add;idx[tail]=id;
                while(tail-head+1>=2 && que[tail]>que[tail-1])que[tail-1]=que[tail],idx[tail-1]=idx[tail],tail--;
            }
          inline void erase(int id){if(idx[head]==id)head++;}
          inline DB maxv(){return tail-head+1>=1?que[head]+add:0.0;}
      }Q1,Q2;
    
    
    DB cir,pos[maxN+10];
    
    inline DB dist(DB p1,DB p2){return p2>=p1 ? p2-p1 : cir+p2-p1; }
    
    inline void move(DB &w,DB l){w+=l;if(w>=cir) w-=cir;}
    
    inline void solve2()
      {
          int i,p1,p2;
          DB w1,w2;
          cir=0.0;re(i,1,cnt)pos[i]=cir,cir+=DB(lon[i]);
          p1=1;
          for(p2=1;pos[p2]<=cir/2.0 && p2!=cnt;p2=next(p2));
          if(p2==cnt && pos[p2]<=cir/2.0)p2=next(p2);
          Q1.clear();Q2.clear();
          re(i,p1,qian(p2))Q1.insert(i,DB(furthestson[root[i]])+pos[i]);
          if(p2!=p1) re(i,p2,qian(p1))Q2.insert(i,DB(furthestson[root[i]])+cir-pos[i]);
          w1=0.0;w2=cir/2.0;
          
          mmst(vis,0);
          vis[1]=1;
          while(vis[2]<2)
            if(dist(w2,pos[p2])<=dist(w1,pos[p1]))
              {
                      DB l=dist(w2,pos[p2]);
                  Q1.add-=l;
                        DB v1=Q1.maxv(),v2=Q2.maxv();
                  upmin(ans,max(v1,v2+l));
                  upmin(ans,max(v2,v1+l));
                  if(v1<=(v1+l+v2)/2.0 && (v1+l+v2)/2.0<=v1+l) upmin(ans,(v1+l+v2)/2.0);
                  Q2.erase(p2);
                  Q2.add+=l;
                  move(w1,l);
                  move(w2,l);
                  Q1.insert(p2,DB(furthestson[root[p2]])+dist(w1,pos[p2]));
                  p2=next(p2);
              }
            else
              {
                  DB l=dist(w1,pos[p1]);
                        Q1.add-=l;
                        DB v1=Q1.maxv(),v2=Q2.maxv();
                        upmin(ans,max(v1,v2+l));
                  upmin(ans,max(v2,v1+l));
                  if(v1<=(v1+l+v2)/2.0 && (v1+l+v2)/2.0<=v1+l) upmin(ans,(v1+l+v2)/2.0);
                        Q1.erase(p1);
                        Q2.add+=l;
                        move(w1,l);
                        move(w2,l);
                        h[p1]=max(Q1.maxv(),Q2.maxv());
                        Q2.insert(p1,DB(furthestson[root[p1]])+dist(pos[p1],w1));
                        p1=next(p1);
                        vis[p1]++;
                    }
        }
    
    inline void solve3()
      {
          int i;
          re(i,0,now)
            {
                int u=edge[i].u,v=edge[i].v;DB l=DB(edge[i].dis);
                if(id[u]!=0 && id[v]!=0)continue;
                if(dep[u]>dep[v]) swap(u,v);
                DB v1=DB(furthestson[v]),v2=max(DB(f[v])-l,DB(dep[u])+h[id[st[u]]]);
                upmin(ans,max(v1,v2+l));
              upmin(ans,max(v2,v1+l));
             
              if(v1<=(v1+l+v2)/2.0 && (v1+l+v2)/2.0<=v1+l) upmin(ans,(v1+l+v2)/2.0);
            }
      }
    
    int main()
      {
          /*freopen("foodshop.in","r",stdin);
          freopen("foodshop.out","w",stdout);*/
          int i;
          N=gint();
            now=-1;mmst(first,-1);
            re(i,1,N)
              {
                  int u=gint(),v=gint(),dis=gint();
                    addedge(u,v,dis);
                    addedge(v,u,dis);
                }
            findround();
            mmst(vis,0);
            re(i,1,cnt)solve1(root[i]);
            ans=1e60;
            solve2();
            solve3();
            PF("%0.1lf
    ",ans);
            return 0;
      }
    View Code
  • 相关阅读:
    NestingQuery
    Repeat
    GenericQuery
    StringOpr
    RHEL5.6 安装 virtualbox
    DNS的资料总结
    drop delete truncate 区别
    Linux Shell命令ulimit的用法
    OSI及TCP/IP的概念和区别
    shell:读取文件的每一行内容并输出
  • 原文地址:https://www.cnblogs.com/maijing/p/4684437.html
Copyright © 2020-2023  润新知