4890: [Tjoi2017]城市

这题题面看这里:https://www.luogu.org/problem/show?pid=3761

这里怎么做呢

看了下数据范围。。

感觉n^2能过

那就暴力枚举删去那一条边咯

然后暴力搞一搞

至于最新的边建在哪里

肯定就是两颗子树的重心啦

至于怎么求重心,看代码吧。。

这样的话每次遍历三次树就可以得出答案了


#include<cstdio>
#include<cstdlib>
#include<cstring>
const int N=5005;
const int MAX=1<<30;
struct qq
{
    int y,c,last;
}s[N*2];
int last[N];
int n;
int S[N],T[N],C[N];
void init (int num,int x,int y,int c)
{
    s[num].y=y;s[num].c=c;
    s[num].last=last[x];
    last[x]=num;
}
int f[N],f1[N];//子树以内的最大值    子树以外的最大值 
int F[N],G[N];//次大值   最大值的位置 
int mymax (int x,int y){return x>y?x:y;}
int mymin (int x,int y){return x<y?x:y;}
int NO;
void dfs (int x,int fa)//更新f值 
{
    f[x]=0;
    for (int u=last[x];u!=-1;u=s[u].last)
    {
        if (NO==u||u==NO+n-1) continue;
        int y=s[u].y;
        if (y==fa) continue;
        dfs(y,x);
        int lalal=f[y]+s[u].c;
        if (f[x]<lalal)
        {
            F[x]=f[x];
            f[x]=lalal;
            G[x]=y;
        }
        else if (F[x]<lalal)
            F[x]=lalal;
    }
}
void dfs1 (int x,int fa)
{
    for (int u=last[x];u!=-1;u=s[u].last)
    {
        if (NO==u||u==NO+n-1) continue;
        int y=s[u].y;
        if (y==fa) continue;
        f1[y]=f1[x]+s[u].c;
        if (G[x]!=y) f1[y]=mymax(f[x]+s[u].c,f1[y]);
        else f1[y]=mymax(F[x]+s[u].c,f1[y]);
        dfs1(y,x);
    }
}
int tmp,tmp1;
int lalal=0;
void get_root (int x,int fa)
{
    if (mymax(f[x],f1[x])<tmp) {tmp=mymax(f[x],f1[x]);tmp1=x;}
    for (int u=last[x];u!=-1;u=s[u].last)
    {
        if (NO==u||u==NO+n-1) continue;
        int y=s[u].y;
        if (y==fa) continue;
        get_root(y,x);
    }
}
  
int main()
{
    int ans=MAX;
    scanf("%d",&n);
    for (int u=1;u<n;u++)
        scanf("%d%d%d",&S[u],&T[u],&C[u]);
    memset(last,-1,sizeof(last));
    for (int u=1;u<n;u++)
        init(u,S[u],T[u],C[u]),init(u+n-1,T[u],S[u],C[u]);
    for (int u=1;u<n;u++)//割掉哪一条边 
    {
        memset(f,0,sizeof(f));
        memset(F,0,sizeof(F));
        NO=u;
        dfs(S[u],0);dfs(T[u],0);
        f1[S[u]]=0;dfs1(S[u],0);
        f1[T[u]]=0;dfs1(T[u],0);    
        int xx,xx1;
        int ans1=0;
        tmp=MAX;get_root(S[u],0);xx=tmp1;
        tmp=MAX;get_root(T[u],0);xx1=tmp1;
        for (int i=1;i<=n;i++) ans1=mymax(ans1,mymax(f[i],f1[i]));
        ans=mymin(ans,mymax(ans1,mymax(f[xx],f1[xx])+mymax(f[xx1],f1[xx1])+C[u]));
        /*printf("%d %d %d\n",xx,f[xx],f1[xx]);
        printf("%d %d %d\n",xx1,f[xx1],f1[xx1]);
        system("pause");*/
    }
    printf("%d\n",ans);
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值