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

思路:

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


#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. 图的绝对中心(bzoj 2180: 最小直径生成树)

    2180: 最小直径生成树 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 219  Solved: 105 [Submit][Status][Dis ...

  2. HDU 2282 Chocolate (最小费用最大流)

    HDU  2282 Chocolate (最小费用最大流) #include <iostream> #include <cstdio> #include <queue&g ...

  3. BZOJ 3218 UOJ #77 A+B Problem (主席树、最小割)

    BZOJ 3218 UOJ #77 A+B Problem (主席树.最小割) 大名鼎鼎的A+B Problem, 主席树优化最小割-- 调题死活调不对,一怒之下改了一种写法交上去A了,但是改写法之后 ...

  4. Strategic game(树的最小点覆盖)

    Strategic game 题意: 一个树,在一个节点放兵,周围的边就被守护,守护所有的边,问最少放多少兵 题解: 这种问题又称树的最小点覆盖 dp[x][1]以x为根的子树全被看住且在x上放置士兵 ...

  5. P1395 会议[链式前向星板](树的最小重心点+所有点到重心距离的和)

    题目描述 有一个村庄居住着 n 个村民,有 n−1 条路径使得这 n 个村民的家联通,每条路径的长度都为 1.现在村长希望在某个村民家中召开一场会议,村长希望所有村民到会议地点的距离之和最小,那么村长 ...

  6. PAT甲题题解-1106. Lowest Price in Supply Chain (25)-(dfs计算树的最小层数)

    统计树的最小层数以及位于该层数上的叶子节点个数即可. 代码里建树我用了邻接链表的存储方式--链式前向星,不了解的可以参考,非常好用: http://www.cnblogs.com/chenxiwenr ...

  7. [UVA-1218] Perfect Service(树的最小支配集)

    题目链接:https://vjudge.net/problem/UVA-1218 题目大意:给你一棵无向树,让你求树的最小支配集,但是有一个要求是除最小支配集外剩下的任何一个结点不能同时连接支配集中的 ...

  8. 关于取整符号(二叉树具有n个结点的m次树的最小高度⌈logₘ(n(m-1)+1)⌉)

    性质4 具有n个结点的m次树的最小高度为 关于取整符号:向上取整⌈⌉和向下取整⌊⌋符号 向下取整的运算称为Floor,用数学符号 ⌊ ⌋ 表示:向上取整的运算称为Ceiling,用数学符号 ⌈ ⌉ 表 ...

  9. POJ 1635 Subway tree systems 树的Hash 或 树的最小表示法

    题目大意: 就是给出从树的中心开始的dfs序, 根据两个dfs序列判断两棵树是否同构 大致思路: 首先根据dfs一直是从树的中心开始的, 所以不用担心中心的问题, 用树的Hash的话当然可以做 另外一 ...

最新文章

  1. 阿里云MVP北京闭门会圆满落幕 多把“利剑”助力开发者破阵蜕变
  2. C#编程总结--总目录
  3. Python入门100题 | 第063题
  4. mysql高效索引之覆盖索引
  5. [NOI2011]阿狸的打字机
  6. java怎样返回json_java怎么返回json
  7. 现代软件工程 作业 4 个人作业
  8. Verify_Execute 验证SQL语句执行结果
  9. Winform主窗体的设置
  10. 如何使用camtasia制作网页视频调查问卷
  11. 不考虑知识点,考代码段更好
  12. 蜂鸣器的专业分类是这样的
  13. golang笔记14--go 语言爬虫实战项目介绍
  14. numpy_multiply函数
  15. fft算法的c语言实现dsp,基于DSP的FFT算法实现.doc
  16. 绘画教程:动漫人体肌肉的详细画法
  17. PyQt5 第六章 拖拽和绘画(二)
  18. 计算机作业我家乡的变化英语作文,家乡的变化 Changes in My Hometown
  19. 开源作者遭受小白的9种伤害
  20. jsplumb使用过程中可能碰见的一些问题

热门文章

  1. HTMLCSS学习笔记(四)----浮动原理及清浮动
  2. Nginx内置变量以及日志格式变量参数详解
  3. 20160522--20160526----mybatis入门基础
  4. bBank Demo 演示(最后更:2010-4-16)
  5. And it's over,And it's a new start
  6. Android点赞音效播放
  7. 微信 WEUI 的 switch button 精简提取
  8. No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=arm64, VALID_ARCHS=armv7 armv7s)
  9. 组队开发第二周第一次会议
  10. distinct 只针对一个字段