码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 2022杭电多校八 1007-Darnassus(kruscal)


    题目链接:杭电多校8 - Virtual Judge

    题目:

     样例输入:

    1. 2
    2. 5
    3. 4 3 5 1 2
    4. 10
    5. 4 7 3 8 6 1 9 10 5 2

    样例输出:

    1. 7
    2. 24

    题意:给出一个排列p,把每个位置视为点,建一个无向图,i,j之间的边权为|i-j|*|pi-pj|。求这个图的最小生成树。

    先来给出最小生成树的一些性质:
    (1)一个图的最小生成树不一定唯一,但是其对应第k大边权一定是唯一的

    (2)最小生成树的最大边权一定是所有生成树的最大边权的最小值

    分析:首先我们尝试着把相邻的点之间连一条边,这样每两个相邻点之间的边权都是|pi-pj|有一棵生成树的边的最大值是小于n的,那么就等价于我们可以构造一棵最小生成树而其中所有边权均小于n,因为最小生成树的最大边权一定是所有生成树的最大边权的最小值。所以最小生成树中所有边权均小于n。那么也就是说我们只需要把所有边权小于n的边记录一下然后跑最小生成树就行。现在问题是我怎么找到边权小于n的边,根据|i-j|*|pi-pj|这道题只能用桶排,用链式前向星写一个h[i]代表权值为i的边的初始编号,记录一下每个边权出现的编号,最后直接跑一个最小生成树就可以了。注意在桶排的时候不要用vector,容易超时,而用链式前向星写会比vector快一倍多。

    下面是代码:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. using namespace std;
    10. const int N=5e4+10;
    11. int fu[N],a[N],mp[N];
    12. int h[N],ne[N*600],idx,u[N*600],v[N*600];
    13. struct node{
    14. int u,v,w;
    15. }p[N*600];
    16. int find(int x)
    17. {
    18. if(x!=fu[x]) fu[x]=find(fu[x]);
    19. return fu[x];
    20. }
    21. void add(int x,int y,int z)
    22. {
    23. u[idx]=x;
    24. v[idx]=y;
    25. ne[idx]=h[z];
    26. h[z]=idx++;
    27. }
    28. int main()
    29. {
    30. int T;
    31. cin>>T;
    32. while(T--)
    33. {
    34. int n;
    35. scanf("%d",&n);
    36. idx=0;
    37. for(int i=1;i<=n;i++)
    38. {
    39. fu[i]=i;h[i]=-1;
    40. scanf("%d",&a[i]);
    41. mp[a[i]]=i;
    42. }
    43. int cnt=0;
    44. for(int i=1;i<=n;i++)
    45. {
    46. int t=(int)sqrt(n);
    47. int e=min(i+t,n);
    48. for(int j=i+1;j<=e;j++)
    49. {
    50. int tt=1ll*(j-i)*abs(a[j]-a[i]);
    51. if(tt
    52. add(i,j,tt);
    53. tt=1ll*abs(mp[j]-mp[i])*(j-i);
    54. if(tt
    55. add(mp[i],mp[j],tt);
    56. }
    57. }
    58. long long ans=0;
    59. int count=0;
    60. for(int i=1;i
    61. {
    62. for(int j=h[i];j!=-1;j=ne[j])
    63. {
    64. int fx=find(u[j]),fy=find(v[j]);
    65. if(fx==fy) continue;
    66. fu[fx]=fy;
    67. count++;ans+=i;
    68. if(count==n-1) break;
    69. }
    70. if(count==n-1) break;
    71. }
    72. printf("%lld\n",ans);
    73. }
    74. return 0;
    75. }
  • 相关阅读:
    企业电子招标采购系统源码Spring Boot + Mybatis + Redis + Layui + 前后端分离 构建企业电子招采平台之立项流程图
    冲量在线出席2022第五届中国信息技术应用创新大会,同与会嘉宾分享基于信创隐私计算一体机促进数据要素市场化的解决方案
    数据可视化工具 ,不会写 SQL 代码也能做数据分析
    IDEA新建一个spark项目
    刷爆力扣之最短无序连续子数组
    [4G/5G/6G专题基础-156]: 什么是物理层信道评估
    NodeJs实战-待办列表(7)-connect组件简化代码
    vite3、vue 项目打包分包进阶-组件分包
    Springboot+vue微信小程序的学生选课系统#毕业设计
    执行java -jar命令,显示jar中没有主清单属性
  • 原文地址:https://blog.csdn.net/AC__dream/article/details/126308484
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号