tayz胡策 day2 T3

提高组(交流赛 DAY2)
3.车站
【问题描述】
城市中有 n 个学校,编号为 1 到 n,已知 n 个学校通过一些道路相连构成一棵树的形状。1
号节点是树的根节点。(叶子节点的管辖区域只有自己本身)这些学校之间存在管辖与被管辖的
关系,每个学校的管辖区域包括这个学校和这个学校子树上所有的学校。现在市长想在城市中建
立一个车站,为了车辆安全,车站需要建在学校里面(建立在节点上)。为了决定最终的方案,
市长需要你帮忙算出在每个学校的管辖区域建立车站(这个车站不一定建在作为根的这个学校上)
的最小不方便度。定义一个学校管辖区域的不方便度为在管辖区域内选定任意一个学校,使得管
辖区域内与选定学校距离最远的学校的距离。
【输入格式】
输入第一行包括 1 个非负整数 n。
接下来n-1 行, 每行包括3 个非负整数ui , vi
, l
i表示编号为ui 和vi 的学校间有一条长度为l
i 的
道路连接。
【输出格式】
输出包含 n 行,每行包含一个非负整数,表示第 i 号学校的管辖区域的最小不方便度。
【输入样例】
6
1 2 5
1 5 6
2 3 2
2 4 1
3 6 1
【输出样例】
8
3
1
0
0
【输入输出样例说明】
以对于以 1 为根的子树为例,选择 1 号学校的不方便度为 1 到 6 的距离,是 8,选择 2 号学
校的不方便度为 2 到 5 的距离,是 11,选择 3 号学校的不方便度为 3 到 5 的距离,是 13,选择 4
号学校的不方便度为 4 到 5 的距离,是 12,选择 5 号学校的不方便度为 5 到 6 的距离,是 14,
选择 6 号学校的不方便度为 6 到 5 的距离,是 14。所以以 1 为根的子树选择 1 号学校最优。
【数据说明】
对于 30% 的数据:n ≤ 100;
对于 70% 的数据:n ≤ 3000;
对于 100% 的数据:n ≤ 300000 1 ≤ ui
,vi ≤ n 0 <= l
i ≤ 10000。
30分暴力 = =floyd预处理

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int d[1000+5][1000+5],fa[1000000];
bool vis[1000005];
struct lc
{
    int f,t,d;
}es[200000];
int tot=0,first[100000],next[200000],dis[1000000];
void build(int f,int t,int d)
{
    es[++tot]=(lc){f,t,d};
    next[tot]=first[f];
    first[f]=tot;
}
int sd[100000];
void dfs(int x)
{
    for(int i=first[x];i!=0;i=next[i])
    {
        int v=es[i].t;
        if(vis[v]==0)
        {
            vis[x]=1;
            sd[v]=sd[x]+1;
            fa[v]=x;
            dfs(v);
        }
    }
}
int ha[100000],tt=0;
void dfs2(int x)
{
    for(int i=first[x];i!=0;i=next[i])
    {
        int v=es[i].t;
        if(sd[v]==sd[x]+1)
        {
            ha[++tt]=v;
            dfs2(v);
        }
    }
}
int main()
{
    freopen("station.in","r",stdin);
    freopen("station.out","w",stdout);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        if(i!=j) d[i][j]=1e9;
    for(int i=1;i<n;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        build(a,b,c);
        build(b,a,c);
        d[a][b]=d[b][a]=c;
    }
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    fa[1]=1;
    sd[1]=1;
    dfs(1);

    for(int i=1;i<=n;i++)
    {
        memset(ha,0,sizeof(ha));
        tt=0;
        ha[++tt]=i;
        dfs2(i);
        int ma=0;
        int ans=1e9+7;
        for(int k=1;k<=tt;k++)
        {
            ma=0;
            for(int j=1;j<=tt;j++)
            {
                ma=max(ma,d[ha[k]][ha[j]]);
            }
            ans=min(ans,ma);
        }
        if(tt==0) cout<<"0"<<endl;
        else cout<<ans<<endl;
    }



    fclose(stdin);
    fclose(stdout);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值