HDU 5624 KK's Reconstruction 最小生成树
题意:这是bc round 71 div 1 的 1004 直接去看中文题意
分析:
首先,一种合法方案对应了原图的一棵生成树。
我们知道,最小生成树有一个性质是最大边最小。
因此,我们可以枚举生成树的最小边,去掉比该边小的边后对新图求最小生成树,那么我们所要的最优解一定包含在其中。
时间复杂度O(Mlog M+M^2*a (N),显然仅仅这个效率是不够的。
可以发现我们每次枚举后都重新求了最小生成树,事实上这是不必要的。
考虑从大到小枚举生成树的最小边,我们要做的实际上是每次加入一条边,维护当前图的最小生成树。
加入一条边时,我们需要判断这条边能否与之前的边构成环。
I 若能构成环,用该边替代环中最大边一定更优;
II 若不能构成环,直接加入该边即可。
找环中最大边可以用DFS 实现。若图中现有的边数为N-1N−1,我们就可以更新答案。
这样,事件复杂度就降到了O(M\log M+MN)O(MlogM+MN)。
更高的效率的方法,我们涉及的操作为加边、删边、查询路径最大边,因此可以使用LCT 来维护。
注:我按照题解写了一发,肯定是我手残,没有理解人家的意思,我发现我写出来还没题解上的效率不行的快
肯定我不行,
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=;
const int mod=1e9+;
const LL INF=INT_MAX;
int head[maxn],p;
struct Edge
{
LL u,v,next;
LL w,mark;
bool operator<(const Edge &e)const
{
return w<e.w;
}
} edge[],o[];
void add(int u,int v,int w)
{
edge[p].u=u;
edge[p].v=v;
edge[p].w=w;
edge[p].mark=;
edge[p].next=head[u];
head[u]=p++;
}
int fa[maxn];
int find(int x)
{
if(x==fa[x])return x;
return fa[x]=find(fa[x]);
}
LL tmp,vv,_max;
void dfs(int u,int f,int res)
{
if(u==vv)
tmp=res;
for(int i=head[u]; ~i; i=edge[i].next)
{
if(edge[i].v==f)continue;
if(edge[i].mark)continue;
_max=max(_max,edge[i].w);
int c=res;
if(res==-||edge[i].w>edge[c].w)c=i;
dfs(edge[i].v,u,c);
}
}
int main()
{
int T,n,m;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=; i<=m; ++i)
scanf("%I64d%I64d%I64d",&o[i].u,&o[i].v,&o[i].w);
sort(o+,o++m);
for(int i=; i<=n; ++i)fa[i]=i;
p=;
memset(head,-,sizeof(head));
int cnt=;
LL ans=INF;
for(int i=m; i>; --i)
{
tmp=-,_max=,vv=o[i].v;
if(cnt==n-)
{
dfs(o[i].u,,-);
ans=min(ans,_max-o[i+].w);
}
int fx=find(o[i].u);
int fy=find(o[i].v);
if(fx!=fy)
{
++cnt;
fa[fx]=fy;
}
else
{
if(tmp==-)
dfs(o[i].u,,-);
edge[tmp].mark=edge[tmp^].mark=;
}
add(o[i].u,o[i].v,o[i].w);
add(o[i].v,o[i].u,o[i].w);
}
if(cnt==n-)
{
_max=;
dfs(,,-);
ans=min(ans,_max-o[].w);
}
if(ans==INF)printf("-1\n");
else printf("%I64d\n",ans);
}
return ;
}
HDU 5624 KK's Reconstruction 最小生成树的更多相关文章
- HDU 5624 KK's Reconstruction
这题目测是数据水了.我这种暴力写法显然是可以卡超时的. 假设有2000个点,15000条边,前面10000条不能构成树,后面5000条可以,这种数据显然可以卡超时. #include <stdi ...
- HDU 5723 Abandoned country 【最小生成树&&树上两点期望】
任意门:http://acm.hdu.edu.cn/showproblem.php?pid=5723 Abandoned country Time Limit: 8000/4000 MS (Java/ ...
- HDU 5723 Abandoned country (最小生成树 + dfs)
Abandoned country 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5723 Description An abandoned coun ...
- HDU 5723 Abandoned country(最小生成树 + 树形DP)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5723 [题目大意] n座城市,m条路径,求解: 1.最短的路径和,使得n座城市之间直接或者间接连通 ...
- Hdu 1301 Jungle Roads (最小生成树)
地址:http://acm.hdu.edu.cn/showproblem.php?pid=1301 很明显,这是一道“赤裸裸”的最小生成树的问题: 我这里采用了Kruskal算法,当然用Prim算法也 ...
- Qin Shi Huang's National Road System HDU - 4081(树形dp+最小生成树)
Qin Shi Huang's National Road System HDU - 4081 感觉这道题和hdu4756很像... 求最小生成树里面删去一边E1 再加一边E2 求该边两顶点权值和除以 ...
- HDU 1162 Eddy's picture (最小生成树)(java版)
Eddy's picture 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1162 ——每天在线,欢迎留言谈论. 题目大意: 给你N个点,求把这N个点 ...
- HDU 5723 Abandoned country(最小生成树+边两边点数)
http://acm.split.hdu.edu.cn/showproblem.php?pid=5723 题意:给出一个无向图,每条路都有一个代价,求出把所有城市连通的最小代价.在此基础上,国王会从这 ...
- hdu 3371 Connect the Cities(最小生成树)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3371 984ms风险飘过~~~ /************************************ ...
随机推荐
- hive-site.xml 参数设置
<?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="confi ...
- iOS 网络编程
iOS 开发中所需的数据基本都是来自网络,网络数据请求是 iOS 编程中必不可少的,应该熟练掌握网络请求. 网络请求方式有 :GET , POST , PUT ,DELETE 等,其中常用的就是 GE ...
- PAT-乙级-1033. 旧键盘打字(20)
1033. 旧键盘打字(20) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 旧键盘上坏了几个键,于是在敲一段文 ...
- 谈谈js中for in 需要注意的地方
js中for in 可以遍历对象或数组的显性属性,也就是说我们自己定义的属性是可以遍历的,那些原型上默认已有的属性,例如:Object.prototype.toString.Object.protot ...
- 20130729--Samba的学习
(一).基本概念 samba是一个能让你的Unix计算机和其它MS Windows计算机相互共享资源的软件. samba提供有关资源共享的三个功能,包括:smbd,执行它可以使Unix能够共享资源给其 ...
- fiddler 插件开发二
本篇主要讲解Fildder插件开发中的涉及到的主要接口与类. 1.IFiddlerExtension 接口 如果要开发的自定义插件有UI界面,则需要实现IFiddlerExtension 接口.你程序 ...
- 找出程序cpu使用率高的原因
确定是CPU过高 使用top观察是否存在CPU使用率过高现象 找出线程 对CPU使用率过高的进程的所有线程进行排序 ps H -e -o pid,tid,pcpu,cmd --sort=pcpu |g ...
- 好看的游戏soul calibur
http://soulcalibur.fr/index.php?wiki/sophitia/ http://astuce-soluce.playfrance.com/index.php/Soul_Ca ...
- 220. Contains Duplicate III
题目: Given an array of integers, find out whether there are two distinct indices i and j in the array ...
- 同步or异步
一.什么是同步?什么是异步? 同步:如果有多个任务要执行,这些任务必须逐个执行,一个任务的执行会导致整个流程的暂时等待,这些任务没有办法并发地执行: 异步:如果有多个任务要执行,这些任务可以并发执行, ...