zoukankan      html  css  js  c++  java
  • [Tjoi2017]城市

    从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作。这个地区一共有ri座城市,《-1条高速公
    路,保证了任意两运城市之间都可以通过高速公路相互可达,但是通过一条高速公路需要收取一定的交通费用。小
    明对这个地区深入研究后,觉得这个地区的交通费用太贵。小明想彻底改造这个地区,但是由于上司给他的资源有
    限,因而小明现在只能对一条高速公路进行改造,改造的方式就是去掉一条高速公路,并且重新修建一条一样的高
    速公路(即交通费用一样),使得这个地区的两个城市之间的最大交通费用最小(即使得交通费用最大的两座城市
    之间的交通费用最小),并且保证修建完之后任意两座城市相互可达。如果你是小明,你怎么解决这个问题?
    Input
    输入数据的第一行为一个整数n,代表城市个数。
    接下来的n - 1行分别代表了最初的n-1条公路情况。
    每一行都有三个整数u,v,d。u,v代表这条公路的两端城市标号,d代表这条公路的交通费用。
    1<=n<=5000
    1 <= u,v <= n,1<= d <= 2000
    Output
    输出数据仅有一行,一个整数,表示进行了最优的改造之后,该地区两城市 之间最大交通费用。
    Sample Input
    5
    1 2 1
    2 3 2
    3 4 3
    4 5 4
    Sample Output
    7

    /*
    此题同ioi2013 dreaming那个题
    枚举下删除的哪一条边,于是整个树变成两个连通块
    对于连通块找出其半径,半径就是树中每个点的最长链的最小值
    因为是希望找出新树的直径尽可能小嘛!
    于是新树的直径可以是原来两个树的直径之一,可是用某条边连接其半径所形成 
    */ 
    #include<bits/stdc++.h>
    #define N 5007
    #define inf 0x3f3f3f3f
    using namespace std;
    int n,m,ans,cnt,dis,res;
    int head[N<<1],mv[N],u[N],v[N],w[N];
    int dp[N][2];
    bool vis[N];
    struct edge
    {
        int u,v,w,nxt;
    }e[N<<1];
    
    inline void add(int u,int v,int w)
    {
        e[++cnt].v=v;
    	e[cnt].w=w;
    	e[cnt].nxt=head[u];
    	head[u]=cnt;
    }
    
    inline int read()
    {
        int x=0,f=1;char c=getchar();
        while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    void getd(int u)
    {
        for(int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if(vis[v]) continue;
            vis[v]=1;
    		getd(v);
            if(dp[u][0]<dp[v][0]+e[i].w)
            {
                dp[u][1]=dp[u][0];mv[u]=v;
                dp[u][0]=dp[v][0]+e[i].w;
            }
            else if(dp[u][1]<dp[v][0]+e[i].w)
                dp[u][1]=dp[v][0]+e[i].w;
        }
    	dis=max(dis,dp[u][0]+dp[u][1]);
    }
    
    void getr(int u,int from)
    {
        res=min(res,max(from,dp[u][0]));
        //半径为每个点的最长链中的最小值 
        for(int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if(!vis[v]) continue;
            vis[v]=0;
            if(mv[u]==v) 
              getr(v,max(dp[u][1]+e[i].w,from+e[i].w));
            else 
              getr(v,max(dp[u][0]+e[i].w,from+e[i].w));
            
        }
    }
    
    void clear()
    {
        memset(dp,0,sizeof dp);
        memset(mv,0,sizeof mv);
        memset(vis,0,sizeof vis);
        res=inf;dis=0;
    }
    
    int main()
    {
        n=read();
        for(int i=1;i<n;i++)
        {
            u[i]=read();v[i]=read();w[i]=read();
            add(u[i],v[i],w[i]);add(v[i],u[i],w[i]);
        }
        int d1,d2,r1,r2;ans=res=inf;dis=0;
        for(int i=1;i<n;i++) //枚举删除哪一条边 
        {
            vis[v[i]]=1;//设第i条边被删除,设右端点已走过 
    		getd(u[i]); //从左端点开始,求这个连通块的直径 
    		d1=dis;
            dis=0;
    		getd(v[i]); 
    		d2=dis;
          
            vis[v[i]]=0;
    		getr(u[i],0); 
    		r1=res;
            res=inf;
    		getr(v[i],0); 
    		r2=res;
            //联通块1,2的半径 
            ans=min(ans,max(max(d1,d2),r1+r2+w[i]));
            //新树直径可能是原来两个树的直径,或用w[i]连接两个树的半径形成,取其最大值 
            clear();
        }
        printf("%d\n",ans);
        return 0;
    }
    

      

  • 相关阅读:
    归并排序模板
    树状数组模板
    KMP模板
    拓扑排序模板
    分布式唯一ID生成算法-雪花算法
    【转载】一起来学Spring Cloud | Eureka Client注册到Eureka Server的秘密
    一起来学Spring Cloud | 第八章:消息总线(Spring Cloud Bus)
    我为什么会成为一个程序猿
    一起来学Spring Cloud | 第七章:分布式配置中心(Spring Cloud Config)
    一起来学Spring Cloud | 第六章:服务网关 ( Zuul)
  • 原文地址:https://www.cnblogs.com/cutemush/p/11748671.html
Copyright © 2011-2022 走看看