zoukankan      html  css  js  c++  java
  • [NOI2013]快餐店

    题目描述

    小T打算在城市C开设一家外送快餐店。送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方。

    快餐店的顾客分布在城市C的N 个建筑中,这N 个建筑通过恰好N 条双向道路连接起来,不存在任何两条道路连接了相同的两个建筑。任意两个建筑之间至少存在一条由双向道路连接而成的路径。小T的快餐店可以开设在任一建筑中,也可以开设在任意一条道路的某个位置上(该位置与道路两端的建筑的距离不一定是整数)。

    现给定城市C的地图(道路分布及其长度),请找出最佳的快餐店选址,输出其与最远的顾客之间的距离。

    输入输出格式

    输入格式:

    输入文件foodshop.in第一行包含一个整数N,表示城市C中的建筑和道路数目。

    接下来N行,每行3个整数,Ai,Bi,Li(1≤i≤N;Li>0),表示一条道路连接了建筑Ai与Bi,其长度为Li 。

    输出格式:

    输出文件foodshop.out仅包含一个实数,四舍五入保留恰好一位小数,表示最佳快餐店选址距离最远用户的距离。

    注意:你的结果必须恰好有一位小数,小数位数不正确不得分。

    输入输出样例

    输入样例#1:
    【样例输入1】
    4 
    1 2 1 
    1 4 2 
    1 3 2 
    2 4 1
    【样例输入2】
    5
    1 5 100
    2 1 77
    3 2 80
    4 1 64
    5 3 41
    输出样例#1:
    【样例输出1】
    2.0 
    【样例输出2】
    109.0

    说明

    样例1

    样例2

    数据范围

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

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

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

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

    显然这是一棵基环树.
    那么先考虑树上的做法,答案就是直径/2.
    现在有一个环了,那么最长链就有可能经过环上的点.
    把环上的每条边去掉之后跑直径,然后取一个最小值就是答案了.
    这样的复杂度是n^2,但只TLE4个点?但还有WA,不知道是写错了还是什么原因.
    最长链要么在某一棵子树里,要么由某两颗子树的最长链和环上的一段组成.
    那么就先预处理出每棵子树中的最长链,记为dis.
    然后把环上的点记一个起点,记一个前缀和.
    那么就设pre[i]i之前的点组成的最长链的长度,suf类似.
    最后枚举每一条边,分三种情况取最大值就是断这一条边的答案.
    复杂度O(n).


     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<string>
     6 #include<algorithm>
     7 #include<map>
     8 #include<complex>
     9 #include<queue>
    10 #include<stack>
    11 #include<cmath>
    12 #include<set>
    13 #include<vector>
    14 #define maxn 100010
    15 #define mk make_pair
    16 #define LL long long
    17 #define inf 1e17
    18 using namespace std;
    19 struct data{
    20   int nex,to,w;
    21 }e[maxn*2];
    22 int head[maxn],edge=-1,dad[maxn],n;
    23 LL dis[maxn],pre[maxn],suf[maxn],p1[2][maxn],p2[2][maxn],sum[2][maxn],ans=0;
    24 bool flag=0,bj[maxn],huan[maxn];
    25 vector<int>clc,eg;
    26 map<pair<int,int>,int>mp;
    27 queue<int>q;
    28 inline void add(int from,int to,int w){
    29   e[++edge].nex=head[from];
    30   e[edge].to=to;
    31   e[edge].w=w;
    32   head[from]=edge;
    33 }
    34 inline void out(int x){
    35   if(flag) return;
    36   int xx=x;x=dad[x];
    37   while(x!=xx) clc.push_back(x),x=dad[x];
    38   clc.push_back(xx);
    39 }
    40 void dfs(int x,int fa){
    41   if(flag) return;
    42   for(int i=head[x];i!=-1;i=e[i].nex){
    43     int v=e[i].to;
    44     if(v==fa) continue;
    45     if(dad[v]) {dad[v]=x;out(v);flag=1;return;}
    46     dad[v]=x;dfs(v,x);
    47   }
    48 }
    49 void dp(int x,int fa){
    50   for(int i=head[x];i;i=e[i].nex){
    51     int v=e[i].to;
    52     if(v==fa || huan[v]) continue;
    53     dp(v,x);
    54     ans=max(ans,dis[x]+dis[v]+e[i].w);
    55     dis[x]=max(dis[v]+e[i].w,dis[x]);
    56   }
    57 }
    58 int main(){
    59   memset(head,-1,sizeof(head));
    60   int x,y,z;
    61   scanf("%d",&n);
    62   for(int i=1;i<=n;i++)
    63     scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z),mp[mk(x,y)]=edge,mp[mk(y,x)]=edge;
    64   dad[1]=1,dfs(1,0);
    65   for(int i=0;i<clc.size();i++) huan[clc[i]]=1;
    66   for(int i=0;i<clc.size();i++) dp(clc[i],0);
    67   int len=clc.size();
    68   p1[0][0]=p2[0][0]=dis[clc[0]];pre[0]=-inf;
    69   for(int i=1;i<len;i++){
    70     int u=clc[i-1],v=clc[i];
    71     sum[0][i]=sum[0][i-1]+e[mp[mk(u,v)]].w;
    72     p1[0][i]=max(p1[0][i-1],dis[v]+sum[0][i]);
    73     p2[0][i]=max(p2[0][i-1],dis[v]-sum[0][i]);
    74     pre[i]=max(pre[i-1],dis[v]+sum[0][i]+p2[0][i-1]);
    75   }
    76   clc.push_back(clc[0]);
    77   p1[1][len]=p2[1][len]=dis[clc[len]];suf[len]=-inf;
    78   for(int i=len-1;i>0;i--){
    79     int u=clc[i+1],v=clc[i];
    80     sum[1][i]=sum[1][i+1]+e[mp[mk(u,v)]].w;
    81     p1[1][i]=max(p1[1][i+1],dis[v]+sum[1][i]);
    82     p2[1][i]=max(p2[1][i+1],dis[v]-sum[1][i]);
    83     suf[i]=max(suf[i+1],dis[v]+sum[1][i]+p2[1][i+1]);
    84   }
    85   LL g=inf;
    86   for(int i=1;i<len;i++){
    87     LL now=p1[0][i-1]+p1[1][i];
    88     now=max(now,max(pre[i-1],suf[i]));
    89     g=min(g,now);
    90   }
    91   printf("%.1lf",(double)max(g,ans)/2);
    92   return 0;
    93 }
  • 相关阅读:
    2015网易校招Java开发工程师(技术架构)在线笔试题
    2015百度校招用户行为分析研发工程师笔试题
    2016届百度实习生前端笔试题上海卷a
    数据库 三范式最简单最易记的解释
    从几个sample来学习JAVA堆、方法区、JAVA栈和本地方法栈
    C++中虚函数和纯虚函数的总结
    MFC一些基本控件操作的总结
    单文档多视图一些基本操作
    MFC单文档静态分割视图
    iOS通讯录相关知识-浅析
  • 原文地址:https://www.cnblogs.com/pantakill/p/7502737.html
Copyright © 2011-2022 走看看