题意:

      给你一个全图,在里面找到一棵树,这棵树最多只有一条边可以不是最小树(也可以是), 要求 那对特殊的边的两个权值/除了这条边其他边的和最大.

思路:

     方法有很多,最少有三种方法,我用两种方法做的,别的暂时没想到(太弱了);

     第一种:

            先求出来一颗最小树,然后枚举树上的边,枚举到每一条边的时候就假设把这条边删除了,然后分成两个集合,我们只要在这两个集合之间连一条边,肯定就是树了,那么怎么连呢,我们可以直接搜索两个集合中分别权值最大的那个点,假设连接这两条边,因为要就该边的权值/非该边的所有和最大,每次枚举相当于分母固定了(最小树 - 当前枚举的边),只要找到最大的分子就行了,所以在两个集合里面找最大的点.就这样遍历到最后,取得最大值就行了.

    第二种:

          第二种是和上面的想法相反的,是分子固定找分母,做法也是先找到一颗最小树,然后枚举所有边,当枚举该边的时候就假设该边就是那个特殊的边,那么权值分子就固定是边的两个点的权值,那么分子呢,分两种情况,如果当前枚举的边不是最小树上的边,那么加上这条边后就一定会形成环,我们既然要比值最大,而且还必须是棵树,那就必须在环上删除一条最大的边(不算当前这条边),如果当前的边是最小树上的边,那么就删除该边就行了,其实两种情况的写法都一样,分母都是 最小树 - max(u ,v),max(u ,v)是树上u,v,之间最长的边,

可以在枚举前搜索一遍求出来树上任意两点之间的最长边(时间是o(n^2));就这样遍历到最后取最小就行了.....

我的两个解法都跑了900多,原因是最小树用的K求的,其实应该用P求会快很多,因为P是针对稠密图的,后来的4756 用K就过不去,必须用P + 树形dp 优化.

最小树 + DFS

#include<stdio.h>

#include<string.h>

#include<math.h>

#include<algorithm>

using namespace std;

typedef struct

{

   int x ,y ,w;

}NODE;

typedef struct

{

   int to ,next;

}STAR;

typedef struct

{

   int a ,b;

   double x;

}EDGE;

NODE node[1100];

EDGE edge[1100 * 1100 /2];

STAR E[1100*2];

int list[1100] ,tot;

int mer[1100] ,MAX;

int mk[1100*2];

bool mark_dfs[1100];

int finds(int x)

{

   if(x == mer[x])

   return x;

   mer[x] = finds(mer[x]);

}

void add(int a ,int b)

{

   E[++tot].to = b;

   E[tot].next = list[a];

   list[a] = tot;

}

bool camp(EDGE a ,EDGE b)

{

   return a.x < b.x;

}

void DFS(int s ,int w)

{

   if(MAX < w)

   MAX = w;

   for(int k = list[s] ;k ;k = E[k].next)

   {

      int to = E[k].to;

      if(mark_dfs[to]) continue;

      mark_dfs[to] = 1;

      DFS(to ,node[to].w);

   }

}

int main ()

{

   int t ,n ,i ,j;

   scanf("%d" ,&t);

   while(t--)

   {

      scanf("%d" ,&n);

      for(i = 1 ;i <= n ;i ++)

      scanf("%d %d %d" ,&node[i].x ,&node[i].y ,&node[i].w);

      int tmp = 0;

      for(i = 1 ;i <= n ;i ++)

      for(j = i + 1 ;j <= n ;j ++)

      {

         int xx = node[i].x - node[j].x;

         int yy = node[i].y - node[j].y;

         double dis = sqrt(xx * xx * 1.0 + yy * yy * 1.0);

         edge[++tmp].a = i;

         edge[tmp].b = j;

         edge[tmp].x = dis;

      }

      

      memset(list ,0 ,sizeof(list));

      tot = 1;

      double sum = 0;

      sort(edge + 1 ,edge + tmp + 1 ,camp);

      int mkt = 0;

      for(i = 1 ;i <= n ;i ++)mer[i] = i;

      

      for(i = 1 ;i <= tmp ;i ++)

      {

         int x = finds(edge[i].a);

         int y = finds(edge[i].b);

         if(x == y) continue;

         mer[x] = y;

         sum += edge[i].x;

         add(edge[i].a ,edge[i].b);

         add(edge[i].b ,edge[i].a);

         mk[++mkt] = i; 

      } 

      double ans = 0;

      for(i = 1 ;i <= mkt ;i ++)

      {

         int ii = mk[i];

         int a = edge[ii].a;

         int b = edge[ii].b;

         MAX = node[a].w;

         memset(mark_dfs ,0 ,sizeof(mark_dfs));

         mark_dfs[a] = mark_dfs[b] = 1;

         DFS(a ,node[a].w);

         int m1 = MAX;

         memset(mark_dfs ,0 ,sizeof(mark_dfs));

         mark_dfs[a] = mark_dfs[b] =1;

         MAX = node[b].w;

         DFS(b ,node[b].w);

         int m2 = MAX;

         

         double aa = (m1 + m2) * 1.0 / (sum - edge[ii].x);

         if(ans < aa)

         ans = aa;

      }

      printf("%.2lf\n" ,ans);

   }

   return 0;

}

有点像次小生成树

#include<stdio.h>

#include<string.h>

#include<math.h>

#include<algorithm>

#define N (1000 + 100)

using namespace std;

typedef struct

{

   int x ,y ,w;

}NODE;

typedef struct

{

   int a ,b;

   double x;

}EDGE;

typedef struct

{

   int to ,next;

   double dis;

}STAR;

NODE node[N];

EDGE edge[N*N/2];

STAR E[N*2];

int list[N] ,tot;

int mark_dfs[N];

double maxe[N][N];

int mer[N];

void add(int a, int b ,double c)

{

   E[++tot].to = b;

   E[tot].dis = c;

   E[tot].next = list[a];

   list[a] = tot;

}

int finds(int x)

{

   if(x == mer[x]) return x;

   return mer[x] = finds(mer[x]);

}

bool camp(EDGE a ,EDGE b)

{

   return a.x < b.x;

}

double maxx(double x ,double y)

{

   return x > y ? x : y;

}

void dfs_max(int s ,double nowmax ,int oo)

{

   for(int k = list[s] ;k ;k = E[k].next)

   {

      int to = E[k].to;

      if(mark_dfs[to]) continue;

      mark_dfs[to] = 1;

      maxe[oo][to] = maxx(nowmax,E[k].dis);

      dfs_max(to ,maxx(nowmax,E[k].dis),oo);

   }

   return;

}

int main ()

{

   int t ,n ,i ,j;

   scanf("%d" ,&t);

   while(t--)

   {

      scanf("%d" ,&n);

      for(i = 1 ;i <= n ;i ++)

      scanf("%d %d %d" ,&node[i].x ,&node[i].y ,&node[i].w);

      int tmp = 0;

      for(i = 1 ;i <= n ;i ++)

      for(j = i + 1 ;j <= n ;j ++)

      {

         int xx = node[i].x - node[j].x;

         int yy = node[i].y - node[j].y;

         double dis = sqrt(xx * xx * 1.0 + yy * yy * 1.0);

         edge[++tmp].a = i;

         edge[tmp].b = j;

         edge[tmp].x = dis;

      }

      

      sort(edge + 1 ,edge + tmp + 1 ,camp);

      memset(list ,0 ,sizeof(list));

      tot = 1;

      double T_sum = 0;

      for(i = 1 ;i <= n ;i ++) mer[i] = i;

      for(i = 1 ;i <= tmp ;i ++)

      {

         int a = edge[i].a;

         int b = edge[i].b;

         int x = finds(a);

         int y = finds(b);

         if(x == y) continue;

         mer[x] = y;

         T_sum += edge[i].x;

         add(a ,b ,edge[i].x);

         add(b ,a ,edge[i].x);

      }

      

      for(i = 1 ;i <= n ;i ++)

      {

         memset(mark_dfs ,0 ,sizeof(mark_dfs));

         mark_dfs[i] = 1;

         dfs_max(i ,0 ,i);

      }

      

      double ans = 0;      

      

      for(i = 1 ;i <= tmp ;i ++)

      {

         int a = edge[i].a;

         int b = edge[i].b;

         double now;

         now = 1.0 * (node[a].w + node[b].w) / (T_sum - maxe[a][b]);

         if(ans < now) ans = now;

      }

      

      printf("%.2lf\n" ,ans);

   }

   return 0;

}

      

         

         

      

   

   

   

 

hdu4081 最小树+DFS或者次小树的变形的更多相关文章

  1. POJ 1679 判断最小树是否唯一

    题意:       给你一个图,问你最小树是否唯一,唯一则输出最小数的权值,不唯一输出Not Unique! 思路:      题目问的是最小树是否唯一,其实也就是在问次小树是否等于最小树,如果等于则 ...

  2. Educational Codeforces Round 17

    Educational Codeforces Round 17 A. k-th divisor 水题,把所有因子找出来排序然后找第\(k\)大 view code //#pragma GCC opti ...

  3. cong

    Directions:  Study the following cartoon carefully and write an essay in which you should 1) descr ...

  4. hbase——b树,b+树,lsm树

    b树 b树,又叫做平衡多路查找树.一个m阶的b树的特性如下: 树中的每个节点,最多有m个子节点. 除了根节点之外,其他的每个节点至少有ceil(m/2)个子节点,ceil函数为取上限函数. 所有的叶子 ...

  5. vsCode安装todo插件

    使用过IDEA或者WebStrom的阿媛应该都知道他们都有一个TODO功能,方便我们跟踪注释,或者说是我们在项目代码里面所做的标记:但是如果你现在在使用vsCode,你会发现,没有TODO功能,幸好, ...

  6. POJ1679判断最小生成树的唯一性

    题意:      判断最小树是否唯一. 思路:      我用了两种方法,主要就是好久没敲了,找个水题练练手,第一种就是先一遍最小生成树,然后枚举最小生成树上的每一条边,然后取消这条边,在跑一遍最小生 ...

  7. hdu4756 最小树+树形dp

    题意:       给你一个完全图,让你在上面找到一颗最小树,然后问破坏这个最小树的某一条边后用其他边连接(要求最小)成新的树,然后输出破坏每一条边后最小树中最大的那个. 思路:       先跑出一 ...

  8. html5 canvas(小树姐的牛掰到爆了的作品)

    自从小树嫁了个牛逼的前端之后,canvas的境界超过我了!!! 小树demo 小编表示:这个境界,这个几何,让我有种跪舔的感觉... http://www.wow-trend.com/brand/in ...

  9. POJ2349二分+并查集,类似最小树的贪心

    题意:       给你n个点,你的任务是构建一颗通讯树,然后给你一个s表示可以选出来s个点两两通讯不花钱,就是费用是0,其他的费用就是两点的距离,有个要求就是其他的费用中最大的那个最小. 思路:   ...

随机推荐

  1. 模式识别Pattern Recognition

    双目摄像头,单目摄像头缺少深度 Train->test->train->test->predicive

  2. C语言经典88案例,我文科妹妹说她都学会了!

    案例ex01: 将字符串转换为一个整数 1 题目 函数:fun() 功能:将字符串转换为一个整数 描述: [不能使用C语言提供的字符串函数] 输入:字符串"-1234" 输出:整型 ...

  3. C#类中的字段、属性和方法

    C#类中的字段.属性和方法 刚开始学C#,对于类中的字段.属性和方法很难分清,写下这份笔记,帮助理解 字段:与类相关的变量 声明方法与声明变量类似,可在前面添加访问修饰符.static关键字等: 属性 ...

  4. 再来认识一下 Java 序列化

    前言 在面试中,Java 序列化被问到的几率还是挺高的.所以搜集了 Java 序列化常见的问题,由浅入深的帮助大家进一步学习和理解. 序列化基础知识 什么是序列化? Java 序列化是 JDK 1.1 ...

  5. ProBuilder快速原型开发技术 ---模型精细化操作

    前面我们讲解了很多ProBuilder功能,但是对于制作一款复杂的模型来说,还远远不够.需要更多的对于模型细节的处理,这就是本篇文章要讲解的"模型精细化操作"技术. 关于PB对于模 ...

  6. 正则表达式-Python实现

    1.概述: Regular Expression.缩写regex,regexp,R等: 正则表达式是文本处理极为重要的工具.用它可以对字符串按照某种规则进行检索,替换. Shell编程和高级编程语言中 ...

  7. Python 随笔2-0319

    一 数据类型 1.整型-int 类型  存年龄.工资.成绩等这样的数据类型可以用int类型 2.浮点型-小数类型(float),带小数点的 3.布尔类型-非真即假  只有这二种:True和Flase, ...

  8. python 查看模块中的方法

    way 1.help() way 2.dir() # dir() 函数不带参数时,返回当前范围内的变量.方法和定义的类型列表: way 3. 使用inspect模块, inspect.getmembe ...

  9. 干掉前端!3分钟纯 Java 注解搭个管理系统

    大家好,我是小富~ 最近接触到个新项目,发现它用了一个比较有意思的框架,可以说实现了我刚入行时候的梦想,所以这里马不停蹄的和大家分享下. 在我刚开始工作接触的项目都还没做前后端分离,经常需要后端来维护 ...

  10. Java代码实现热部署

    一.思路 0. 监听java文件最后修改时间,如果发生变化,则表示文件已经修改,进行重新编译 1. 编译java文件为 class文件 2. 通过手写类加载器,加载 class文件 ,创建对象 3. ...