hdu4081 最小树+DFS或者次小树的变形
题意:
给你一个全图,在里面找到一棵树,这棵树最多只有一条边可以不是最小树(也可以是), 要求 那对特殊的边的两个权值/除了这条边其他边的和最大.
思路:
方法有很多,最少有三种方法,我用两种方法做的,别的暂时没想到(太弱了);
第一种:
先求出来一颗最小树,然后枚举树上的边,枚举到每一条边的时候就假设把这条边删除了,然后分成两个集合,我们只要在这两个集合之间连一条边,肯定就是树了,那么怎么连呢,我们可以直接搜索两个集合中分别权值最大的那个点,假设连接这两条边,因为要就该边的权值/非该边的所有和最大,每次枚举相当于分母固定了(最小树 - 当前枚举的边),只要找到最大的分子就行了,所以在两个集合里面找最大的点.就这样遍历到最后,取得最大值就行了.
第二种:
第二种是和上面的想法相反的,是分子固定找分母,做法也是先找到一颗最小树,然后枚举所有边,当枚举该边的时候就假设该边就是那个特殊的边,那么权值分子就固定是边的两个点的权值,那么分子呢,分两种情况,如果当前枚举的边不是最小树上的边,那么加上这条边后就一定会形成环,我们既然要比值最大,而且还必须是棵树,那就必须在环上删除一条最大的边(不算当前这条边),如果当前的边是最小树上的边,那么就删除该边就行了,其实两种情况的写法都一样,分母都是 最小树 - 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或者次小树的变形的更多相关文章
- POJ 1679 判断最小树是否唯一
题意: 给你一个图,问你最小树是否唯一,唯一则输出最小数的权值,不唯一输出Not Unique! 思路: 题目问的是最小树是否唯一,其实也就是在问次小树是否等于最小树,如果等于则 ...
- Educational Codeforces Round 17
Educational Codeforces Round 17 A. k-th divisor 水题,把所有因子找出来排序然后找第\(k\)大 view code //#pragma GCC opti ...
- cong
Directions: Study the following cartoon carefully and write an essay in which you should 1) descr ...
- hbase——b树,b+树,lsm树
b树 b树,又叫做平衡多路查找树.一个m阶的b树的特性如下: 树中的每个节点,最多有m个子节点. 除了根节点之外,其他的每个节点至少有ceil(m/2)个子节点,ceil函数为取上限函数. 所有的叶子 ...
- vsCode安装todo插件
使用过IDEA或者WebStrom的阿媛应该都知道他们都有一个TODO功能,方便我们跟踪注释,或者说是我们在项目代码里面所做的标记:但是如果你现在在使用vsCode,你会发现,没有TODO功能,幸好, ...
- POJ1679判断最小生成树的唯一性
题意: 判断最小树是否唯一. 思路: 我用了两种方法,主要就是好久没敲了,找个水题练练手,第一种就是先一遍最小生成树,然后枚举最小生成树上的每一条边,然后取消这条边,在跑一遍最小生 ...
- hdu4756 最小树+树形dp
题意: 给你一个完全图,让你在上面找到一颗最小树,然后问破坏这个最小树的某一条边后用其他边连接(要求最小)成新的树,然后输出破坏每一条边后最小树中最大的那个. 思路: 先跑出一 ...
- html5 canvas(小树姐的牛掰到爆了的作品)
自从小树嫁了个牛逼的前端之后,canvas的境界超过我了!!! 小树demo 小编表示:这个境界,这个几何,让我有种跪舔的感觉... http://www.wow-trend.com/brand/in ...
- POJ2349二分+并查集,类似最小树的贪心
题意: 给你n个点,你的任务是构建一颗通讯树,然后给你一个s表示可以选出来s个点两两通讯不花钱,就是费用是0,其他的费用就是两点的距离,有个要求就是其他的费用中最大的那个最小. 思路: ...
随机推荐
- 订单和产品的多对多表关系在crudapi系统零代码实现
表关系管理 在上一篇序列号管理中,产品和销售订单都是孤立的单表,本文通过crudapi中表关系(relation)管理将多个表连接起来,形成一个整体. 概要 关系类型 表与表之间的关系(relatio ...
- 鸿蒙开源第三方件组件——轮播组件Banner
目录: 1.功能展示 2.Sample解析 3.Library解析 4.<鸿蒙开源第三方组件>系列文章合集 前言 基于安卓平台的轮播组件Banner(https://github.com/ ...
- 1.1 Python3基础-前言
>>返回主目录 Python 交互式代码 Python 脚本式代码 第一段Python代码: print('Hello World!') >>返回主目录
- 浅谈.Net Core后端单元测试
目录 1. 前言 2. 为什么需要单元测试 2.1 防止回归 2.2 减少代码耦合 3. 基本原则和规范 3.1 3A原则 3.2 尽量避免直接测试私有方法 3.3 重构原则 3.4 避免多个断言 3 ...
- 扫盲贴|如何评价一款App的稳定性和质量?
作者:友盟+移动开发专家 张文 「崩溃」与「卡顿」.「异常退出」等一样,是影响App稳定性常见的三种情况.相关数据显示,当iOS的崩溃率超过0.8%,Android的崩溃率超过0.4%的时候,活跃用户 ...
- css整理之-----------技巧、黑魔法
css 看起来比较简单,但是要想做的好也不是那么容易,我们在平时开发中,主要用css 来美化我们的html结构,所有我觉得css 还是挺重要的,这里记录整理一些关于css 的技巧以及容易忘记的知识点. ...
- android消息线程和消息队列
基于消息队列的线程通信: 消息队列与线程循环 MessageQueue: 利用链表来管理消息. Mess ...
- SpringCloud 中 Feign 调用使用总结
最近做微服务架构的项目,在用 feign 来进行服务间的调用.在互调的过程中,难免出现问题,根据错误总结了一下,主要是请求方式的错误和接参数的错误造成的.在此进行一下总结记录. 以下通过分为三种情况说 ...
- Spring Cloud 升级之路 - 2020.0.x - 1. 背景知识、需求描述与公共依赖
1. 背景知识.需求描述与公共依赖 1.1. 背景知识 & 需求描述 Spring Cloud 官方文档说了,它是一个完整的微服务体系,用户可以通过使用 Spring Cloud 快速搭建一个 ...
- 利用别名切换索引流程Elasticsearch 7.7
背景 公司里面现在有es集群,由于时间过长,es集群中的某个索引过大但是未删除,一直在写入的情况下,昨天写入突然停止了,发现是索引超时的问题,这时想到通过创建一个新的索引来进行索引切换 操作 es 集 ...