zoukankan      html  css  js  c++  java
  • bzoj 3242: [Noi2013]快餐店 章鱼图

    3242: [Noi2013]快餐店

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 266  Solved: 140
    [Submit][Status]

    Description

    小 T打算在城市C开设一家外送快餐店。送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近 的地方。 快餐店的顾客分布在城市C的N 个建筑中,这N 个建筑通过恰好N 条双向道路连接起来,不存在任何两条道路连接了相同的两个建筑。任意两个建筑之间至少存在一条由双向道路连接而成的路径。小T的快餐店可以开设在任一建筑 中,也可以开设在任意一条道路的某个位置上(该位置与道路两端的建筑的距离不一定是整数)。 现给定城市C的地图(道路分布及其长度),请找出最佳的快餐店选址,输出其与最远的顾客之间的距离。 



    Input

    第一行包含一个整数N,表示城市C中的建筑和道路数目。
    接下来N行,每行3个整数,Ai,Bi,Li(1≤i≤N;Li>0),表示一条道路连接了建筑Ai与Bi,其长度为Li 。

    Output

    仅包含一个实数,四舍五入保留恰好一位小数,表示最佳快餐店选址距离最远用户的距离。
    注意:你的结果必须恰好有一位小数,小数位数不正确不得分。

    Sample Input

    1 2 1
    1 4 2
    1 3 2
    2 4 1

    Sample Output

    2.0

    HINT

    数据范围

    对于 10%的数据,N<=80,Li=1;

    对于 30%的数据,N<=600,Li<=100;

    对于 60% 的数据,N<=2000,Li<=10^9;

    对于 100% 的数据,N<=10^5,Li<=10^9

      枚举环上所有边,删掉边转化成树球直径。

      另,用stack实现dfs不能直接改造成tarjan

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define MAXN 110000
    #define MAXV MAXN*2
    #define MAXE MAXV*2
    #define INF 0x3f3f3f3f3f3f3f3fLL
    #define MAXT MAXN*4
    #define lch (now<<1)
    #define rch (now<<1^1)
    #define smid ((sgt[now].l+sgt[now].r)>>1)
    typedef long long qword;
    struct sgt_node
    {
            int l,r;
            pair<qword,int> r1,r2;
    }sgt[MAXT];
    qword val1[MAXN];
    qword val2[MAXN];
    void Build_sgt(int now,int l,int r)
    {
            sgt[now].l=l;sgt[now].r=r;
            if (l==r)
            {
                    sgt[now].r1.first=val1[l];
                    sgt[now].r1.second=l;
                    sgt[now].r2.first=val2[l];
                    sgt[now].r2.second=l;
                    return ;
            }
            Build_sgt(lch,l,smid);
            Build_sgt(rch,smid+1,r);
            sgt[now].r1=max(sgt[lch].r1,sgt[rch].r1);
            sgt[now].r2=max(sgt[lch].r2,sgt[rch].r2);
    }
    pair<qword,int> Query_sgt1(int now,int l,int r)
    {
            if (l>r)return make_pair(-INF,-1);
            if (l==sgt[now].l && r==sgt[now].r)
                    return sgt[now].r1;
            if (r<=smid)
                    return Query_sgt1(lch,l,r);
            else if (l>smid)
                    return Query_sgt1(rch,l,r);
            else
                    return max(Query_sgt1(lch,l,smid),Query_sgt1(rch,smid+1,r));
    }
    pair<qword,int> Query_sgt2(int now,int l,int r)
    {
            if (l>r)return make_pair(-INF,-1);
            if (l==sgt[now].l && r==sgt[now].r)
                    return sgt[now].r2;
            if (r<=smid)
                    return Query_sgt2(lch,l,r);
            else if (l>smid)
                    return Query_sgt2(rch,l,r);
            else
                    return max(Query_sgt2(lch,l,smid),Query_sgt2(rch,smid+1,r));
    }
    
    
    
    
    struct Edge
    {
            int np;
            qword val1;
            Edge *next,*neg;
    }E[MAXE],*V[MAXV];
    int tope=-1;
    void addedge(int x,int y,qword z)
    {
            E[++tope].np=y;
            E[tope].val1=z;
            E[tope].next=V[x];
            V[x]=&E[tope];
    }
    int pnt[MAXN];
    int vis[MAXN];
    int stack[MAXV],tops=-1;
    qword rdis[MAXN];
    qword pdis[MAXN];
    int dfn[MAXN],dfstime;
    int chead,ctail;
    qword clen;
    
    void dfs(int now)
    {
            Edge *ne;
            dfn[now]=++dfstime;
            for (ne=V[now];ne;ne=ne->next)
            {
                    if (ne->np==pnt[now])continue;
                    if (dfn[ne->np])
                    {
                            if (dfn[ne->np]<dfn[now])
                            {
                            ctail=now;
                            chead=ne->np;
                            clen=ne->val1+rdis[now]-rdis[ne->np];
                            }
                            continue;
                    }
                    rdis[ne->np]=rdis[now]+ne->val1;
                    pdis[ne->np]=ne->val1;
                    pnt[ne->np]=now;
                    dfs(ne->np);
            }
    }
    qword tdis[MAXN];
    int pnt2[MAXN];
    qword dfs2(int now,int p,qword d)
    {
            qword mxdpth=d;
            Edge *ne;
            stack[++tops]=now;
            pnt2[now]=p;
            tdis[now]=d;
            while(~tops)
            {
                    now=stack[tops--];
                    for (ne=V[now];ne;ne=ne->next)
                    {
                            if (ne->np==pnt2[now])continue;
                            pnt2[ne->np]=now;
                            tdis[ne->np]=tdis[now]+ne->val1;
                            mxdpth=max(mxdpth,tdis[now]+ne->val1);
                            stack[++tops]=ne->np;
                    }
            }
            return mxdpth;
    }
    qword dist[MAXV];
    int pntt[MAXV];
    qword dfs3(int now,int x1,int x2)
    {
            Edge *ne;
            stack[++tops]=now;
            dist[now]=0;
            pntt[now]=now;
            qword mxdis=0;
            int mxid=now;
            while (~tops)
            {
                    now=stack[tops--];
                    if (mxdis<dist[now])
                            mxdis=dist[now],mxid=now;
                    for (ne=V[now];ne;ne=ne->next)
                    {
                            if (ne->np==pntt[now] || ne->np==x1 || ne->np==x2)continue;
                            dist[ne->np]=dist[now]+ne->val1;
                            pntt[ne->np]=now;
                            stack[++tops]=ne->np;
                    }
            }
            now=mxid;
            mxdis=0;
            pntt[now]=now;
            stack[++tops]=now;
            dist[now]=0;
            while (~tops)
            {
                    now=stack[tops--];
                    if (mxdis<dist[now])
                            mxdis=dist[now],mxid=now;
                    for (ne=V[now];ne;ne=ne->next)
                    {
                            if (ne->np==pntt[now] || ne->np==x1 || ne->np==x2)continue;
                            dist[ne->np]=dist[now]+ne->val1;
                            pntt[ne->np]=now;
                            stack[++tops]=ne->np;
                    }
            }
            return mxdis;
    }
    qword seq0[MAXN];
    qword seq[MAXN];
    qword prvdis0[MAXN];
    qword prvdis[MAXN];
    int que[MAXN];
    qword qres2[MAXN];
    qword qres3[MAXN];
    void solve1(int m)
    {
            int head=0,tail=-1;
            prvdis[0]=prvdis0[0];
            for (int i=1;i<m;i++)
                    prvdis[i]=prvdis0[i]+prvdis[i-1];
            for (int i=0;i<m;i++)
                    seq[i]=seq0[i]-prvdis[i];
            for (int i=0;i<m;i++)
            {
                    while (head<=tail && prvdis[i]-prvdis[que[head]]>clen/2)head++;
                    if (head<=tail)
                            qres2[i]=seq[que[head]]+prvdis[i];
                    while (tail>=head && seq[que[tail]]<=seq[i])tail--;
                    que[++tail]=i;
            }
            head=0,tail=-1;
            prvdis[0]=prvdis0[0];
            for (int i=0;i<m-1;i++)
                    prvdis0[i]=prvdis0[i+1];
            prvdis0[m-1]=prvdis0[m-m/2-1];
            prvdis[m-1]=prvdis0[m-1];
            for (int i=m-2;i>=0;i--)
                    prvdis[i]=prvdis0[i]+prvdis[i+1];
            for (int i=m-1;i>=0;i--)
                    seq[i]=seq0[i]-prvdis[i];
            for (int i=m-1;i>=0;i--)
            {
                    while (head<=tail && prvdis[i]-prvdis[que[head]]>clen/2)head++;
                    if (head<=tail)
                            qres3[i]=seq[que[head]]+prvdis[i];
                    while (tail>=head && seq[que[tail]]<=seq[i])tail--;
                    que[++tail]=i;
            }
            return ;
    }
    qword solve2(int n)
    {
            prvdis[0]=prvdis0[0];
            for (int i=1;i<n;i++)
                    prvdis[i]=prvdis[i-1]+prvdis0[i];
            for (int i=0;i<n;i++)
                    val1[i]=seq0[i]-prvdis[i];
            for (int i=0;i<n;i++)
                    val2[i]=seq0[i]+prvdis[i];
            Build_sgt(1,0,n-1);
            int x;
            qword res=INF;
            for (int i=0;i<n;i++)
            {
                    x=i;
                    pair<qword,int> r1,r2,r3;
                    pair<qword,int> ra,rb;
                    if (i>x)
                    {
                            r1=Query_sgt1(1,0,x-1);
                            r1.first+=prvdis[x]+seq0[x];
                            r2=Query_sgt2(1,x+1,i-1);
                            r2.first+=-prvdis[x]+seq0[x];
                            r3=Query_sgt1(1,i,n-1);
                            r3.first+=prvdis[n-1];
                            r3.first+=prvdis[x]+seq0[x];
                            ra=max(r1,r2);
                            ra=max(ra,r3);
                    }else
                    {
                            r1=Query_sgt1(1,i,x-1);
                            r1.first+=prvdis[x]+seq0[x];
                            r2=Query_sgt2(1,x+1,n-1);
                            r2.first+=-prvdis[x]+seq0[x];
                            r3=Query_sgt2(1,0,i-1);
                            //r3.first+=-prvdis[0];
                            r3.first+=(prvdis[n-1]-prvdis[x])+seq0[x];
                            ra=max(r1,r2);
                            ra=max(ra,r3);
                    }
                    x=ra.second;
                    if (i>x)
                    {
                            r1=Query_sgt1(1,0,x-1);
                            r1.first+=prvdis[x]+seq0[x];
                            r2=Query_sgt2(1,x+1,i-1);
                            r2.first+=-prvdis[x]+seq0[x];
                            r3=Query_sgt1(1,i,n-1);
                            r3.first+=prvdis[n-1];
                            r3.first+=prvdis[x]+seq0[x];
                            rb=max(r1,r2);
                            rb=max(rb,r3);
                    }else
                    {
                            r1=Query_sgt1(1,i,x-1);
                            r1.first+=prvdis[x]+seq0[x];
                            r2=Query_sgt2(1,x+1,n-1);
                            r2.first+=-prvdis[x]+seq0[x];
                            r3=Query_sgt2(1,0,i-1);
                            //r3.first+=-prvdis[0];
                            r3.first+=(prvdis[n-1]-prvdis[x])+seq0[x];
                            rb=max(r1,r2);
                            rb=max(rb,r3);
                    }
                    res=min(res,rb.first);
            }
            return res;
    }
    int main()
    {
        //    freopen("input.txt","r",stdin);
            int n;
            int x,y,z;
            scanf("%d",&n);
            for (int i=1;i<=n;i++)
            {
                    scanf("%d%d%d",&x,&y,&z);
                    addedge(x,y,z);
                    addedge(y,x,z);
                    //    V[x]->neg=V[y];V[y]->neg=V[x];
            }
            dfs(1);
            Edge *ne;
            int pn=chead;
            for (int i=ctail;dfn[i]>=dfn[chead];pn=i,i=pnt[i])
            {
                    for (ne=V[i];ne;ne=ne->next)
                    {
                            if (i==chead && (ne->np==ctail || ne->np==pn))continue;
                            if (i!=chead && (ne->np==pn || ne->np==pnt[i]))continue;
                            tdis[i]=max(tdis[i],dfs2(ne->np,i,ne->val1));
                    }
            }
            int l=0;
            for (int i=ctail;dfn[i]>=dfn[chead];i=pnt[i])
            {
                    seq0[l]=seq[l]=tdis[i];
                    if (i==chead)
                            prvdis0[l+1]=clen-(rdis[ctail]-rdis[chead]);
                    else
                            prvdis0[l+1]=pdis[i];
                    l++;
            }
            prvdis0[0]=prvdis0[l];
            for (int i=0;i<l;i++)
                    seq[l+i]=seq[i],seq0[l+i]=seq0[i],prvdis0[l+i]=prvdis0[i];
            qword ans=INF;
            for (int i=1;i<=l;i++)
                    if (prvdis0[i]>clen/2)
                            ans=min(ans,(prvdis0[i])+seq[i-1]+seq[i]);
            ans=solve2(l);
            solve1(l*2);
            int la=l;
            l=0;
            pn=chead;
            for (int i=ctail;dfn[i]>=dfn[chead];pn=i,i=pnt[i])
            {
                    int x1,x2;
                    if (i==chead)
                    {
                            x1=pn;x2=ctail;
                    }else
                    {
                            x1=pnt[i],x2=pn;
                    }
                    qword x=max(max(qres2[l],qres2[l+la]),max(qres3[l],qres3[l+la]));
                    addedge(++n,i,x);
                    addedge(i,n,x);
                    ans=max(ans,dfs3(i,x1,x2));
                    l++;
            }
            printf("%lld.%c
    ",ans/2,ans%2?'5':'0');
    }
    by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

    本博客已停用,新博客地址:http://mhy12345.xyz

  • 相关阅读:
    javascript基础学习三---DOM操作
    小程序-微信开发者工具使用
    回溯算法实践--工作分配问题
    回溯算法理解
    贪心算法--删数问题
    单线程与多线程的区别
    【图解】Web前端实现类似Excel的电子表格
    详细了解JS Map,它和传统对象有什么区别?
    带你彻底弄懂nth-of-type与nth-child的区别
    input 纯数字输入 限制长度 限制 最大值
  • 原文地址:https://www.cnblogs.com/mhy12345/p/4316542.html
Copyright © 2011-2022 走看看