题意:

      给你一棵树,让你改变一条边,改变之后依然是一棵树,然后问你怎样改变才能让树的直径最短。这里的改变一条边指的是指把一条边长度不变,连在别的两个点上。

思路:

      首先求出树的直径,把直径上的边记录下来,然后在枚举这些边(枚举别的边没意义)每次枚举我的做法是后建造两棵树,我们只要在这两棵树之间连接一条边就行了,但是怎么连接呢? 我是先没别求两棵树的直径,然后在找到直径上中间点,然后连接这两棵树的中间点,只有这样才能保证最短,每次连接后的直径就是 两棵树的直径,和当前枚举的边长度+两个树被中间点分开的较长的那一个值的和,他们三个中较长的哪一个,就这样在所有中找到一个最小的就是答案。


#include<stdio.h>
#include<string.h>
#include<queue>
#include<map> #define N_node 2500 + 5
#define N_edge 5000 + 5
#define INF 1000000000

using namespace
std; typedef struct
{
int
to ,next ,cost;
}
STAR; typedef struct
{
int
a ,b ,c;
}
EDGE; STAR E[N_edge];
EDGE edge[N_node];
int
list[N_node] ,tot;
int
s_x[N_node] ,mer[N_node];
map<int ,map<int ,int> >hash; void add(int a ,int b ,int c)
{

E[++tot].to = b;
E[tot].cost = c;
E[tot].next = list[a];
list[a] = tot; E[++tot].to = a;
E[tot].cost = c;
E[tot].next = list[b];
list[b] = tot;
} void
Spfa(int s ,int n)
{
for(int
i = 0 ;i <= n ;i ++)
s_x[i] = INF ,mer[i] = i;
int
mark[N_node] = {0};
s_x[s] = 0 ,mark[s] = 1;
queue<int>q;
q.push(s);
while(!
q.empty())
{
int
xin ,tou;
tou = q.front();
q.pop();
mark[tou] = 0;
for(int
k = list[tou] ;k ;k = E[k].next)
{

xin = E[k].to;
if(
s_x[xin] > s_x[tou] + E[k].cost)
{

s_x[xin] = s_x[tou] + E[k].cost;
mer[xin] = tou;
if(!
mark[xin])
{

mark[xin] = 1;
q.push(xin);
}
}
}
}
return ;
} int
abss(int x)
{
return
x > 0 ? x : -x;
} int
maxx(int x ,int y)
{
return
x > y ? x : y;
} int main ()
{
int
t ,n ,a ,b ,c ,i ,j;
int
cas = 1;
scanf("%d" ,&t);
while(
t--)
{

scanf("%d" ,&n);
memset(list ,0 ,sizeof(list));
tot = 1;
for(
i = 1 ;i < n ;i ++)
{

scanf("%d %d %d" ,&edge[i].a ,&edge[i].b ,&edge[i].c);
edge[i].a ++ ,edge[i].b ++;
add(edge[i].a ,edge[i].b ,edge[i].c);
} int
p01 ,p02;
Spfa(1 ,n);
int
maxxx = -1;
for(
j = 1 ;j <= n ;j ++)
if(
maxxx < s_x[j] && s_x[j] != INF)
{

maxxx = s_x[j];
p01 = j;
}

Spfa(p01 ,n);
maxxx = -1;
for(
j = 1 ;j <= n ;j ++)
if(
maxxx < s_x[j] && s_x[j] != INF)
{

maxxx = s_x[j];
p02 = j;
}
int
x = p02;
hash.clear();
while(
x != mer[x])
{

hash[x][mer[x]] = hash[mer[x]][x] = 1;
x = mer[x];
} int
ans = INF;
for(
i = 1 ;i < n ;i ++)
{
if(!
hash[edge[i].a][edge[i].b]) continue;
memset(list ,0 ,sizeof(list)) ,tot = 1;
for(
j = 1 ;j < n ;j ++)
if(
j == i) continue;
else
add(edge[j].a ,edge[j].b ,edge[j].c); int p11 ,p12 ,mid1 ,l1 ,mid1l;
Spfa(edge[i].a ,n);
int
max = -1;
for(
j = 1 ;j <= n ;j ++)
if(
max < s_x[j] && s_x[j] != INF)
{

max = s_x[j];
p11 = j;
}

Spfa(p11 ,n);
max = -1;
for(
j = 1 ;j <= n ;j ++)
if(
max < s_x[j] && s_x[j] != INF)
{

max = s_x[j];
p12 = j;
}

l1 = max;
int
x = p12;
int
min = INF;
while(
x != mer[x])
{
if(
min > abss(s_x[x] - (l1 - s_x[x])))
{

min = abss(s_x[x] - (l1 - s_x[x]));
mid1 = x;
mid1l = maxx(s_x[x] ,l1 - s_x[x]);
}

x = mer[x];
}
if(
min > abss(s_x[x] - (l1 - s_x[x])))
{

min = abss(s_x[x] - (l1 - s_x[x]));
mid1 = x;
mid1l = maxx(s_x[x] ,l1 - s_x[x]);
} int
p21 ,p22 ,mid2 ,l2 ,mid2l;
Spfa(edge[i].b ,n);
max = -1;
for(
j = 1 ;j <= n ;j ++)
if(
max < s_x[j] && s_x[j] != INF)
{

max = s_x[j];
p21 = j;
}

Spfa(p21 ,n);
max = -1;
for(
j = 1 ;j <= n ;j ++)
if(
max < s_x[j] && s_x[j] != INF)
{

max = s_x[j];
p22 = j;
}

l2 = max;
x = p22;
min = INF;
while(
x != mer[x])
{
if(
min > abss(s_x[x] - (l2 - s_x[x])))
{

min = abss(s_x[x] - (l2 - s_x[x]));
mid2 = x;
mid2l = maxx(s_x[x] ,l2 - s_x[x]);
}

x = mer[x];
}
if(
min > abss(s_x[x] - (l2 - s_x[x])))
{

min = abss(s_x[x] - (l2 - s_x[x]));
mid2 = x;
mid2l = maxx(s_x[x] ,l2 - s_x[x]);
} int
now = maxx(maxx(l1 ,l2) ,edge[i].c + mid1l + mid2l);
if(
ans > now) ans = now;
}

printf("Case %d: %d\n" ,cas ++ ,ans);
}
return
0;
}

hdu 3721 树的最小直径的更多相关文章

  1. hdu 3721 树的直径

    思路:枚举+树的直径 #include<iostream> #include<cstring> #include<cstdio> #include<algor ...

  2. HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)

    HDU 1394 Minimum Inversion Number(线段树求最小逆序数对) ACM 题目地址:HDU 1394 Minimum Inversion Number 题意:  给一个序列由 ...

  3. HDU 1954 Subway tree systems (树的最小表示法)

    题意:用一个字符串表示树,0代表向下走,1代表往回走,求两棵树是否同构. 分析:同构的树经过最小表示会转化成两个相等的串. 方法:递归寻找每一棵子树,将根节点相同的子树的字符串按字典序排列,递归回去即 ...

  4. HDU 4607 Park Visit 树的最大直径

    题意: 莱克尔和她的朋友到公园玩,公园很大也很漂亮.公园包含n个景点通过n-1条边相连.克莱尔太累了,所以不能去参观所有点景点. 经过深思熟虑,她决定只访问其中的k个景点.她拿出地图发现所有景点的入口 ...

  5. hdu 4612 无向图连通分量缩点,然后求树的最大直径

    #pragma comment(linker,"/STACK:102400000,102400000") #include <iostream> #include &l ...

  6. Warm up HDU - 4612 树的直径

    题意:给出n个点和m条边的无向图,存在重边,问加一条边以后,剩下的桥的数量最少为多少. 题解: 你把这个无向图缩点后会得到一个只由桥来连接的图(可以说这个图中的所有边都是桥,相当于一棵树),然后我们只 ...

  7. bzoj2180: 最小直径生成树

    Description 输入一个无向图G=(V,E),W(a,b)表示边(a,b)之间的长度,求一棵生成树T,使得T的直径最小.树的直径即树的最长链,即树上距离最远的两点之间路径长度. Input 输 ...

  8. hdu 5274 树链剖分

    Dylans loves tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  9. 【学习笔记】最小直径生成树(MDST)

    简介 无向图中某一点(可以在顶点上或边上),这个点到所有点的最短距离的最大值最小,那么这个点就是 图的绝对中心. 无向图所有生成树中,直径最小的一个,被称为 最小直径生成树. 图的绝对中心的求法 下文 ...

随机推荐

  1. 话说 synchronized

    一.前言 ​ 说起java的锁呀,我们先想到的肯定是synchronized[ˈsɪŋ krə naɪ zd]了 ,这个单词很拗口,会读这个单词在以后的面试中很加分(我面试过一些人 不会读 ,他们说的 ...

  2. Hadoop的常用命令

    注:hadoop的使用命令包含 hadoop fs 开头 or hdfs dfs开头 等多种形式来操作. 这里以hadoo fs的形式来介绍在这些命令 1.列出根目录下所有的目录或文件 hadoop ...

  3. pytorch(02)tensor的概念以及创建

    二.张量的简介与创建 2.1张量的概念 张量的概念:Tensor 张量是一个多维数组,它是标量.向量.矩阵的高维拓展 Tensor与Variable Variable是torch.autograd(t ...

  4. 简单的webRTC连接测试

    webRTC WebRTC (Web Real-Time Communications) 是一项实时通讯技术,它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-P ...

  5. MySQL基础知识:Character Set和Collation

    A character set is a set of symbols and encodings. A collation is a set of rules for comparing chara ...

  6. 关于Java中Collections.sort和Arrays.sort的稳定性问题

    一 问题的提出   关于Java中Collections.sort和Arrays.sort的使用,需要注意的是,在本文中,比较的只有Collections.sort(List<T> ele ...

  7. Java并发编程之锁机制

    锁分类 悲观锁与乐观锁 悲观锁认为对于同一个数据的并发操作,一定是会发生修改的,哪怕没有修改,也会认为修改.因此对于同一个数据的并发操作,悲观锁采取加锁的形式.悲观的认为,不加锁的并发操作一定会出问题 ...

  8. C# - 实现类型的比较

    IComparable<T> .NET 里,IComparable<T>是用来作比较的最常用接口. 如果某个类型的实例需要与该类型的其它实例进行比较或者排序的话,那么该类型就可 ...

  9. python那些需要知道的事儿——逻辑运算与比大小

    一.逻辑运算 逻辑运算符: and   or   not,结果为布尔值(True和False) 1.基本逻辑运算符介绍 not :将后面的逻辑运算结果取反 >>> not 1 < ...

  10. MongoDB 那些事(一文以蔽之)

    前言 身边一直都有小伙伴在问:MongoDB到底是什么?它有到底什么特性?有什么与众不同?在什么情况下使用MongoDB最合适?以什么样的姿势是最好的?难道就一定要用吗?....说实话,这些问题都问到 ...