题面



\(solution:\)

这道题很奇妙,需要对kruskal重构树有足够的了解!我们先对王牌电缆实行kruskal重构树,然后我们再来枚举每一条李牌电缆,我们将某一条李牌电缆加进这棵树中必然构成一颗基环树,然后我们必须在这个环上去掉一条王牌电缆,而这我们就可以用树上倍增来完成了!(这样做是正确的,仔细想一下为什么我们kruskal重构的树一定是最优解)



\(code:\)

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>#define ll long long
#define db double
#define inf 0x7fffffff
#define rg register intusing namespace std;struct su{ //王牌电线int x,y,v,z;inline bool operator <(su x){return v<x.v;}
}a[200005];struct pi{ //树的边int to,next,v,z;
}k[100005];struct ya{ //倍增求LCAint x,v,z;
}f[100005][17],c;int n,w,l,top; //意义如题
int ans1,ans2,qu,li;//后两个是存的去的哪一条王牌电线以及对应加的那一条李牌电线
int s[100005]; //并查集
int q[100005]; //BFS预处理
int dp[100005]; //这个点的深度
int tou[100005]; //连接这个点的边
bool vis[100005]; //我又没有访问过
bool shu[200005]; //这条电线我会不会用inline int qr(){ char ch; //快读while((ch=getchar())<'0'||ch>'9');int res=ch^48;while((ch=getchar())>='0'&&ch<='9')res=res*10+(ch^48);return res;
}inline ya max(ya x,ya y){return x.v>y.v?x:y;}
inline ya max(ya x,ya y,ya z){return x.v>y.v?(x.v>z.v?x:z):(y.v>z.v?y:z);}inline void print(int x,int y){ //输出printf("%d\n",x);for(rg i=1;i<=w;++i)if(shu[i])printf("%d\n",i);//有用这条王牌电线就输出printf("%d\n",y);
}inline int get(int x){ //并查集return s[x]==x?x:(s[x]=get(s[x]));
}inline void add(int x,int y,int v,int z){k[++top]=pi{y,tou[x],v,z};k[++top]=pi{x,tou[y],v,z};tou[y]=top; tou[x]=top-1;//加双向边
}inline void yu(){ //树上倍增的预处理q[1]=1;dp[1]=1;vis[1]=1;int l=0,r=1,i;while(l<r){ i=q[++l];for(rg j=0;j<16;++j){if(!f[f[i][j].x][j].x)break;f[i][j+1]=max(f[i][j],f[f[i][j].x][j]);f[i][j+1].x=f[f[i][j].x][j].x;//注意先后顺序防覆盖}for(rg j=tou[i];j;j=k[j].next){if(vis[k[j].to])continue;int to=k[j].to;f[to][0].z=k[j].z;f[to][0].v=k[j].v;f[to][0].x=i;//dp[to]=dp[i]+1;vis[to]=1; q[++r]=to;//}}
}inline ya ask(int x,int y){ //最近公共祖先,及其路径上的最大边权if(dp[x]<dp[y])swap(x,y);ya res; res.v=0;for(rg i=16;i>=0;--i)if(dp[f[x][i].x]>=dp[y])res=max(res,f[x][i]),x=f[x][i].x;for(rg i=16;i>=0;--i)if(f[x][i].x!=f[y][i].x){res=max(res,f[x][i]);//先取值再更新xres=max(res,f[y][i]);x=f[x][i].x,y=f[y][i].x;//注意先后}else if(x==y)return res;return max(res,f[x][0],f[y][0]);
}inline void kruskal(){ int t=0;for(rg i=1;i<=n;++i)s[i]=i;//最小生成树for(rg i=1;i<=w;++i)if(get(a[i].x)!=get(a[i].y)){s[get(a[i].x)]=get(a[i].y);add(a[i].x,a[i].y,a[i].v,a[i].z);shu[a[i].z]=1;ans1+=a[i].v;++t; //我们需要同时记住这条边的信息}if(t==n-1)return ;rg x,y,v,j; ans2=inf;//仅靠王牌不能联通就直接枚举用那条李边划算for(rg i=1;i<=l;++i){x=qr(),y=qr(),v=qr();if(get(x)!=get(y)&&ans2>v) ans2=v,j=i;//能用的权值最小的}print(ans2+ans1,j),exit(0);
}int main(){freopen("telephone.in","r",stdin);freopen("telephone.out","w",stdout);n=qr(),w=qr(),l=qr();for(rg i=1;i<=w;++i)a[i]=su{qr(),qr(),qr(),i};sort(a+1,a+w+1);kruskal();yu();//排序,最小生成树,预处理for(rg i=1,v;i<=l;++i){ //c=ask(qr(),qr()); v=qr();if(!li||ans2>ans1-c.v+v){//更新最优解ans2=ans1-c.v+v;shu[qu]=1;shu[c.z]=0;//要把上一个去掉的加回来!li=i; qu=c.z;//记录去掉那条边,加上那条边}}print(ans2,li);//输出return 0;
}

转载于:https://www.cnblogs.com/812-xiao-wen/p/10388435.html

jzoj4313 电话线铺设(最小生成树+最近公共祖先)相关推荐

  1. NOIp 图论算法专题总结 (1):最短路、最小生成树、最近公共祖先

    系列索引: NOIp 图论算法专题总结 (1) NOIp 图论算法专题总结 (2) NOIp 图论算法专题总结 (3) 最短路 Floyd 基本思路:枚举所有点与点的中点,如果从中点走最短,更新两点间 ...

  2. [树上倍增][最小生成树]JZOJ P4313——电话线铺设

    Description Input Output Sample Input 6 9 4 6 3 4 2 5 6 5 4 6 1 3 5 3 5 9 5 6 8 4 1 5 4 6 4 6 2 7 2 ...

  3. 最近的题目总结(树,电话线铺设,我的天)

    总结 树 solution 电话线铺设 Description input output 数据 solution 我的天 solution 几天没打博客了,现在记录一下一些比较好的题目. 树 Desc ...

  4. 356 次小生成树(求解最近公共祖先优化)

    1. 问题描述: 给定一张 N 个点 M 条边的无向图,求无向图的严格次小生成树.设最小生成树的边权之和为 sum,严格次小生成树就是指边权之和大于 sum 的生成树中最小的一个. 输入格式 第一行包 ...

  5. 树上倍增法求最近公共祖先LCA

    LCA,最近公共祖先,这个东西有很多作用,因此,如何高效求出LCA就成了一个热点的讨论话题. 下面所有的讨论都以图中这棵树为例子. 先来了解下什么是倍增吧,倍增其实就是二分的逆向,二分是逐渐缩小范围, ...

  6. Tarjan算法求无向图割边割点、最近公共祖先的总结

     无向图tarjan求割边割点.最近公共祖先总结 割点:删除这个点之后整个图变成不连通的两个部分的点 割点集合:在一个无向图中删除该集合中的所有点,能使原图变成互不相连的连通块的点的集合 点连通度 ...

  7. 有一个1亿结点的树,已知两个结点, 求它们的最低公共祖先!

    对该问题,分为如下几种情形讨论: 情形一: 假如该树为二叉树,并且是二叉搜索树, 依据二叉搜索树是排过序的, 我们只需要从树的根结点开始,逐级往下,和两个输入的结点进行比较. 如果当前结点的值比两个结 ...

  8. 二叉树:最近的公共祖先 Lowest Common Ancestor of a Binary Tree

    已知二叉树,求二叉树中给定的两个节点的最近公共祖先. 最近公共祖先: 两节点v与w的最近公共祖先u,满足在树上最低(离根最 远),且v,w两个节点都是u的子孙. 如上二叉树,6和8号节点的公共祖先有4 ...

  9. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)...

    转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2194090a96bbed2db1351de8.html 基本概念: 1.割点:若删掉某点后,原连通图 ...

最新文章

  1. Tensorrt一些优化技术介绍
  2. 站在历史的长河中做农活
  3. memcache php mysql_PHP中的数据库二、memcache
  4. kubernetes(六)k8s核心组件学习
  5. 迪普科技以近50%份额全面中标国家电网2016信息化硬件采购
  6. 休眠锁定模式–乐观锁定模式如何工作
  7. HubbleDotNet开源全文搜索数据库项目--技术详解
  8. mysql安全实验测验答案_实验四∶数据库安全性实验报告.doc
  9. Largest Submatrix SPOJ - MINSUB (单调栈)
  10. Indigo Untyped Channel
  11. html怎么设置华文行楷,css如何修改字体为华文行楷
  12. ip计算机网络适配器,如何更改计算机网络ip
  13. 如何提升Javascript 基础
  14. 开学季征文 | 一位开发实习生的真情流露
  15. 神威太湖之光超级计算机搭载了40960,神威·太湖之光超级计算机上实现了千万核超大规模并行计算...
  16. android代码获取deviceid,获取安卓系统的设备id用getDeviceId()函数
  17. 中国作家维权联盟向苹果和百度发出律师函
  18. 【盲信道估计】基于matlab的LMS盲信道估计QPSK仿真
  19. Tita OKR:目标地图的妙用
  20. 树莓派安装部署OpenVINO

热门文章

  1. birt 报表设计(2)—介绍
  2. [原创]网银在线chinabank安全漏洞之“不完善的开发软件包”
  3. 西安市2008驾照理论考试题
  4. 全阶滑模观测器程序_滑模观测器转子估算程序
  5. 设计一个处理两种类型地址的地址簿程序_短信平台的API接口都有哪些类型?
  6. 10kv配电网潮流 matlab,关于用matlab计算配电网三相潮流计算,请大家帮忙检验下!...
  7. 三条中线分的六个三角形_初中数学——与三角形有关的线段
  8. 【Mac Buf Install Solution】Mac Buf Not Provide support for this old version Solution
  9. python123判断性别程序_听说胎心能够预测宝宝性别?这是真的吗?
  10. Java虚拟机(七)——本地方法接口与本地方法栈