洛谷P3761:[TJOI2017]城市

题目描述

从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作。这个地区一共有ri座城市,《-1条高速公路,保证了任意两运城市之间都可以通过高速公路相互可达,但是通过一条高速公路需要收取一定的交通费用。小明对这个地区深入研究后,觉得这个地区的交通费用太贵。小明想彻底改造这个地区,但是由于上司给他的资源有限,因而小明现在只能对一条高速公路进行改造,改造的方式就是去掉一条高速公路,并且重新修建一条一样的高速公路(即交通费用一样),使得这个地区的两个城市之间的最大交通费用最小(即使得交通费用最大的两座城市之间的交通费用最小),并且保证修建完之后任意两座城市相互可达。如果你是小明,你怎么解决这个问题?

输入输出格式

输入格式

输入数据的第一行为一个整数n,代表城市个数。

接下来的n - 1行分别代表了最初的n-1条公路情况。每一行都有三个整数u,v,d。u,v代表这条公路的两端城市标号,d代表这条公路的交通费用。

1 <= u,v <= n,1<= d <= 2000

输出格式

输出数据仅有一行,一个整数,表示进行了最优的改造之后,该地区两城市 之间最大交通费用。

输入输出样例

输入样例#1:

5

1 2 1

2 3 2

3 4 3

4 5 4

输出样例#1:

7

说明

对于30%的数据,1<=n<500

对于100%的数据,1<=n<=5000


想法

很显然,最优解中去掉的那条边一定在原先这棵树的直径上,否则交通费用最大的两个点之间距离没有缩短。

n这么小,可以枚举每条去掉的边。

去掉一条边后原图变为两棵树,将这两棵树连起来后,交通费用最大为max{第一棵树的直径,第二棵树的直径,两棵树的“重心”到最远结点的距离和+这条边的长度}

这里所说的树的“重心”指树中的一个结点,它到树中任意节点的距离最大值 最小

树的直径求法:

随便找一个点u,找到树中到它距离最远的点v

再找到树中到v距离最远的点w,v到w的距离即为树的直径。

(简单证明:假设树的直径为s-t 。首先对于s-t上任意一点,到它距离最远的点为s或t;对于不在s-t上的点u,它与到它距离最远的点之间的路径上一定与s-t有相交,到这个交点距离最远的点为s或t,则到u距离最远的点为s或t)

树的“重心”求法:

用两个数组mx1[]与mx2[],分别记录到某点u的最远距离 及 次远距离(次远距离所在路径与最远距离所在路径唯一交点为u

第一遍dfs,记录结点u到其子树中任意点的mx1[]与mx2[]

第二遍dfs,记录节点u到整棵树中任意点的mx1[]与mx2[]


代码

(P.S.由于我太懒了,所以直接枚举去掉每一条边,不光是直径上的[捂脸])

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>

#define INF 200000000

using namespace std;

const int N = 5005;

struct node{
    int v,len;
    node *next;
}pool[N<<1],*h[N];
int cnt;

void addedge(int u,int v,int len){
    node *p=&pool[++cnt],*q=&pool[++cnt];
    p->v=v;p->next=h[u];h[u]=p;p->len=len;
    q->v=u;q->next=h[v];h[v]=q;q->len=len;
}

int dist[N],vis[N];
int dfs_len(int u,int vv){
    int v,w,ret=u;
    vis[u]=1; dist[u]=0;
    for(node *p=h[u];p;p=p->next)
        if(!vis[v=p->v] && v!=vv){
            w=dfs_len(v,vv);
            if(dist[u]<dist[v]+p->len){
                dist[u]=dist[v]+p->len;
                ret=w;
            }
        }
    vis[u]=0;
    return ret;
}
int diameter(int u,int vv){
    int v=dfs_len(u,vv);
    int w=dfs_len(v,vv);
    return dist[v];
}

int mx1[N],mx2[N];
void dfs1(int u,int vv){
    int v;
    vis[u]=1;
    mx1[u]=mx2[u]=0;
    for(node *p=h[u];p;p=p->next)
        if(!vis[v=p->v] && v!=vv){
            dfs1(v,vv);
            if(mx1[u]<=mx1[v]+p->len){
                mx2[u]=mx1[u];
                mx1[u]=mx1[v]+p->len;
            }
            else if(mx2[u]<mx1[v]+p->len)
                mx2[u]=mx1[v]+p->len;
        }
    vis[u]=0;
}
int dfs2(int u,int vv){
    int v,w,ret;
    vis[u]=1;
    ret=mx1[u];
    for(node *p=h[u];p;p=p->next)
        if(!vis[v=p->v] && v!=vv){
            if(mx1[u]==mx1[v]+p->len)
                w=p->len+mx2[u];
            else w=p->len+mx1[u];
            if(w>=mx1[v])
                mx2[v]=mx1[v],mx1[v]=w;
            else if(w>mx2[v])
                mx2[v]=w;
            ret=min(ret,dfs2(v,vv));
        }
    vis[u]=0;
    return ret;
}

int solve(int s,int t,int len){
    int ret=0,w=len;
    memset(vis,0,sizeof(vis));
    ret=max(diameter(s,t),diameter(t,s));
    dfs1(s,t); w+=dfs2(s,t);
    dfs1(t,s); w+=dfs2(t,s);
    return max(ret,w);
}

int fa[N];
int dfs(int u){
    int v,ret=INF;
    for(node *p=h[u];p;p=p->next)
        if(!fa[v=p->v]){
            ret=min(ret,solve(u,v,p->len));
            fa[v]=u;
            ret=min(ret,dfs(v));
        }
    return ret;
}
int n;

int main()
{
    int u,v,len;
    scanf("%d",&n);
    for(int i=1;i<n;i++)
        scanf("%d%d%d",&u,&v,&len),addedge(u,v,len);

    fa[1]=-1;
    printf("%d\n",dfs(1));

    return 0;
}

原文地址:https://www.cnblogs.com/lindalee/p/8379317.html

时间: 2024-11-08 04:35:42

洛谷P3761:[TJOI2017]城市的相关文章

洛谷P2782 友好城市

题目描述 有一条横贯东西的大河,河有笔直的南北两岸,岸上各有位置各不相同的N个城市.北岸的每个城市有且仅有一个友好城市在南岸,而且不同城市的友好城市不相同.没对友好城市都向政府申请在河上开辟一条直线航道连接两个城市,但是由于河上雾太大,政府决定避免任意两条航道交叉,以避免事故.编程帮助政府做出一些批准和拒绝申请的决定,使得在保证任意两条航道不相交的情况下,被批准的申请尽量多. 输入输出格式 输入格式: 第1行,一个整数N(1<=N<=5000),表示城市数. 第2行到第n+1行,每行两个整数,

洛谷 2782友好城市

题目背景 无 题目描述 有一条横贯东西的大河,河有笔直的南北两岸,岸上各有位置各不相同的N个城市.北岸的每个城市有且仅有一个友好城市在南岸,而且不同城市的友好城市不相同.没对友好城市都向政府申请在河上开辟一条直线航道连接两个城市,但是由于河上雾太大,政府决定避免任意两条航道交叉,以避免事故.编程帮助政府做出一些批准和拒绝申请的决定,使得在保证任意两条航道不相交的情况下,被批准的申请尽量多. 输入输出格式 输入格式: 第1行,一个整数N(1<=N<=5000),表示城市数. 第2行到第n+1行,

洛谷 P2782 友好城市

P2782 友好城市 题目描述 有一条横贯东西的大河,河有笔直的南北两岸,岸上各有位置各不相同的N个城市.北岸的每个城市有且仅有一个友好城市在南岸,而且不同城市的友好城市不相同.每对友好城市都向政府申请在河上开辟一条直线航道连接两个城市,但是由于河上雾太大,政府决定避免任意两条航道交叉,以避免事故.编程帮助政府做出一些批准和拒绝申请的决定,使得在保证任意两条航道不相交的情况下,被批准的申请尽量多. 输入输出格式 输入格式: 第1行,一个整数N,表示城市数. 第2行到第n+1行,每行两个整数,中间

洛谷P3758:[TJOI2017]可乐

题目描述 加里敦星球的人们特别喜欢喝可乐.因而,他们的敌对星球研发出了一个可乐机器人,并且放在了加里敦星球的1号城市上.这个可乐机器人有三种行为: 停在原地,去下一个相邻的城市,自爆.它每一秒都会随机触发一种行为.现 在给加里敦星球城市图,在第0秒时可乐机器人在1号城市,问经过了t秒,可乐机器人的行为方案数是多少? 输入输出格式 输入格式 第一行输入两个正整数况N,M,N表示城市个数,M表示道路个数.(1 <= N <=30,0 < M < 100) 接下来M行输入u,v,表示u,

洛谷P3759 - [TJOI2017]不勤劳的图书管理员

Portal Description 给出一个\(1..n(n\leq5\times10^4)\)的排列\(\{a_n\}\)和数列\(\{w_n\}(w_i\leq10^5)\),进行\(m(m\leq5\times10^4)\)次操作: 交换\(a_{p_1},a_{p_2}\),并求\(\sum_{i=1}^n \sum_{j=i+1}^n [a_i>a_j](w_{a_i}+w_{a_j})\). Solution 树套树/CDQ分治,想锻炼一下代码能力所以写了树套树. 首先这是一个求逆

洛谷 模拟城市2.0

一次洛谷月赛的T1,当时因为是信心赛,认为第一题应该不会太难,结果想了很久,直接额放弃正解选择暴力...简直就是巨坑的五维DP...mmd 题目背景 博弈正在机房颓一个叫做<模拟城市2.0>的游戏. 2048年,经过不懈努力,博弈终于被组织委以重任,成为D市市委书记! 他勤学好问,励精图治,很快把D市建设成富强民主文明和谐的美好城市.为了进一步深化发展,他决定在海边建立一个经济开发区. 题目描述 已知开发区的建筑地块是一个n×n的矩形,而开发区可以建造三种建筑: 商业楼,住宅楼,教学楼.这任何

洛谷P1265 公路修建(Prim)

To 洛谷.1265 公路修建 题目描述 某国有n个城市,它们互相之间没有公路相通,因此交通十分不便.为解决这一“行路难”的问题,政府决定修建公路.修建公路的任务由各城市共同完成. 修建工程分若干轮完成.在每一轮中,每个城市选择一个与它最近的城市,申请修建通往该城市的公路.政府负责审批这些申请以决定是否同意修建. 政府审批的规则如下: (1)如果两个或以上城市申请修建同一条公路,则让它们共同修建: (2)如果三个或以上的城市申请修建的公路成环.如下图,A申请修建公路AB,B申请修建公路BC,C申

洛谷P1027 Car的旅行路线

洛谷P1027 Car的旅行路线 题目描述 又到暑假了,住在城市A的Car想和朋友一起去城市B旅游.她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t. 图例(从上而下) 机场 高速铁路 飞机航线 注意:图中并没有 标出所有的铁路与航线. 那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来

洛谷P1462 通往奥格瑞玛的道路

P1462 通往奥格瑞玛的道路 219通过 1.2K提交 题目提供者gconeice 标签二分图论洛谷原创 难度提高+/省选- 提交该题 讨论 题解 记录 最新讨论 RE好多.. 到底怎么判断AFK啊 看不懂题目.. 建议修改题目 究竟是血量为负算挂还是生命… 题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡奥格瑞玛 题目描述 在艾泽拉斯,有n个城市.编号为1,2,3,...,