3242: [Noi2013]快餐店 树的直径 环套树

本文介绍了一种解决特定图论问题的算法——如何在一个由建筑物和道路构成的城市地图上找到最优位置来开设快餐店,使得从该位置到任何顾客所在地的距离最小化。文章通过深度优先搜索和动态规划的方法详细阐述了解决方案,并附上了完整的C++实现代码。

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

题解:

我是%栋老师的,感觉他写得很好啊。我又犯了个很sb的错误,首先我找环的时候就挺傻的,两次dfs,还没有把非树边给ban掉,于是就GG了……

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=100010;
const int inf=2147483647;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
int n;
LL D,pre1[Maxn],pre2[Maxn],suf1[Maxn],suf2[Maxn],dd[Maxn],mx[Maxn];
int vis[Maxn],P1,P2,cir[Maxn],lenc=0;
LL sd[Maxn];
bool mark[Maxn];
struct Edge{int y,next;LL d;}e[Maxn<<1];
int last[Maxn],len=1;
void ins(int x,int y,LL d)
{
    int t=++len;
    e[t].y=y;e[t].d=d;
    e[t].next=last[x];last[x]=t;
}
int ban;
void DFS1(int x,int fa)
{
    vis[x]=1;
    for(int i=last[x];i;i=e[i].next)
    {
        int y=e[i].y;
        if(y==fa)continue;
        if(!vis[y])DFS1(y,x);
        else P1=y,P2=x,D=e[i].d,ban=i;
    }
}
bool DFS2(int x,int fa)
{
    vis[x]=2;
    bool flag=(x==P2);
    if(flag)cir[++lenc]=x;
    for(int i=last[x];i;i=e[i].next)
    {
        int y=e[i].y;
        if(y==fa||i==ban||(i^1)==ban)continue;
        if(vis[y]!=2)
        {
            bool t=DFS2(y,x);
            if(t)cir[++lenc]=x,dd[lenc-1]=e[i].d;
            flag|=t;
        }
    }
    mark[x]=flag;
    return flag;
}
LL tt;
LL dfs(int x,int fa)
{
    LL mx1=0,mx2=0;
    for(int i=last[x];i;i=e[i].next)
    {
        int y=e[i].y;
        if(y==fa||mark[y])continue;
        LL o=(LL)e[i].d+dfs(y,x);
        if(o>mx1)mx2=mx1,mx1=o;
        else if(o>mx2)mx2=o;
    }
    tt=max(tt,mx1+mx2);
    return mx1;
}
int main()
{
    LL tmp=0;
    n=read();
    for(int i=1;i<=n;i++)
    {
        int x=read(),y=read(),d=read();
        ins(x,y,d),ins(y,x,d);
    }
    DFS1(1,0);
    DFS2(P1,0);
    dd[lenc]=D;
    sd[0]=sd[1]=0;
    for(int i=1;i<=lenc;i++)
    {
        tt=0;
        mx[i]=dfs(cir[i],0);
        tmp=max(tmp,tt);
        if(i>1)sd[i]=sd[i-1]+(LL)dd[i-1];
    }
    pre1[1]=mx[1];
    for(int i=2;i<=lenc;i++)pre1[i]=max(pre1[i-1],(LL)mx[i]+sd[i]);
    suf1[lenc]=mx[lenc];
    for(int i=lenc-1;i;i--)suf1[i]=max(suf1[i+1],(LL)mx[i]+sd[lenc]-sd[i]);
    LL t;
    t=mx[1];
    pre2[1]=mx[1];
    for(int i=2;i<=lenc;i++)
    {
        t+=(LL)dd[i-1];
        pre2[i]=max(pre2[i-1],t+mx[i]);
        t=max(t,mx[i]);
    }
    t=mx[lenc];
    suf2[lenc]=mx[lenc];
    for(int i=lenc-1;i;i--)
    {
        t+=(LL)sd[i+1]-sd[i];
        suf2[i]=max(suf2[i+1],t+mx[i]);
        t=max(t,mx[i]);
    }
    LL ans=max(tmp,pre2[lenc]);
    for(int i=1;i<lenc;i++)
    ans=min(ans,max(max(pre2[i],suf2[i+1]),max(pre1[i]+suf1[i+1]+D,tmp)));
    printf("%.1lf",(double)ans/2.0);
}
【源码免费下载链接】:https://renmaiwang.cn/s/afwyp 在统计学与概率论中,概率分布是一种用来描述随机变量可能取值的概率或者一组值出现的概率的函数。本文将详细介绍几种常见的概率分布类型,并提供它们的定义公式与图像。### 一、伯努利分布(Bernoulli Distribution)**定义**:伯努利分布是最简单的离散概率分布之一,它描述的是只有两种可能结果的随机试验,通常表示为成功(1)或失败(0)。如果成功的概率为\( p \),则失败的概率为\( 1-p \)。**概率质量函数**:\[ P(X = x) = \begin{cases} p & \text{if } x = 1 \\1 - p & \text{if } x = 0\end{cases} \]**图像**:伯努利分布的图像非常简单,只包含两个点,分别对应于\( x = 0 \)和\( x = 1 \)。### 二、二项分布(Binomial Distribution)**定义**:二项分布是伯努利试验的扩展,描述了在\( n \)次独立重复的伯努利试验中成功次数的概率分布,其中每次试验的成功概率都是\( p \)。**概率质量函数**:\[ P(X = k) = \binom{n}{k} p^k (1-p)^{n-k} \]其中,\( \binom{n}{k} \)表示组合数,即从\( n \)个不同元素中取出\( k \)个元素的不同组合方式的数量。**图像**:二项分布的图像根据\( p \)和\( n \)的不同而变化。当\( p \)接近0.5且\( n \)较大时,分布趋向于对称;反之,则可能呈现出偏斜的形状。### 三、泊松分布(Poisson Distribution)**定义**:泊松分布适用于描述单位时间内事件发生的次数的概率分布,尤其适用于稀有事件。例如,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值