题意:给定一个带权边无向图,求最小生成树,且满足第一个节点的度为固定的k 无解则输出-1

数据规模: 节点数n和限制k<=5000 边数m<=10^5 时限8sec

思路:

首先时限比较宽,第一个想到的暴力做法是枚举第一个节点(即首都)选中的K条边,复杂度为阶乘级别 无法接受。但是我们可以确定,问题的关键在于在所有国道中选择哪k条国道。一旦k条国道选定,最小生成树就是固定的。

考虑一个极端的情况,如果我们直接对这个图运行Kruskal算法,得到了一个树 且 第一个节点的度为k,则这就是正确的答案。当然,一般数据是无法做到的。

那么我们就可以使用一个技巧,如果运行Kruskal算法后第一个节点的度小于k,那么我们在算法运行的序列中将所有国道的位置整体向前移动,使得下一次运行Kruskal算法可以选定更多的国道,我们就离正确答案更近了。反之亦然。

那么怎样调整所有“国道”在Kruskal序列中的位置呢?

选定一个double值mid 它可以很大,也可以很小,在排序时“国道”的权值加上这个mid再与非国道比较,就可以适当的调节所有“国道”在序列中的位置。

代码如下,只要理解了排序比较函数cmp 也就理解了这个Kruskal的变种算法了。

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<algorithm>
using namespace std;
const int maxn=+,maxm=+;
int x[maxm],y[maxm],w[maxm],sig[maxm],ance[maxn],ans[maxn];
int n,m,k,tot,cnt,captedge;
double l,r,mid;
bool cmp(int a,int b)
{
return (w[a]+(x[a]==)*mid)<(w[b]+(x[b]==)*mid);//这个算法的核心
}
int findance(int x)
{
if(x==ance[x])return x;
else return ance[x]=findance(ance[x]);
}
void Kruskal(bool flag)
{
cnt=captedge=;
for(int i=;i<=n;i++)
{
ance[i]=i;
}
sort(sig,sig+m,cmp);
for(int i=;i<m;i++)
{
if(cnt+==n) return ;
int j=sig[i];
int u=findance(x[j]),v=findance(y[j]);
if((u!=v)&&(flag||(captedge+(x[j]==))<=k)) {
ance[u]=v;
ans[cnt++]=j;
if(x[j]==)captedge++;
}
}
}
int main()
{
ios::sync_with_stdio(false);
freopen("t.txt","r",stdin);
cin>>n>>m>>k;
tot=;
for(int i=;i<m;i++)
{
sig[i]=i;
cin>>x[i]>>y[i]>>w[i];
if(x[i]>y[i]){int t=x[i];x[i]=y[i];y[i]=t;}//swap
if(x[i]==)tot++;
}
if((k>tot)||(k==&&n>))
{
cout<<"-1"<<endl;
return ;
}
cnt=;
Kruskal();
if(cnt!=(n-))
{
cout<<"-1"<<endl;
return ;
}
l=(-)*100000.0;
r=100000.0;
while(((l+1e-)<r)&&(captedge!=k))
{
mid=(l+r)/2.0;
Kruskal();
if(captedge<k)r=mid;
else l=mid;
}
if(captedge!=k)mid=(l+r)/2.0;
Kruskal();
cout<<n-<<endl;
if(cnt>=)cout<<ans[]+;
for(int i=;i<cnt;i++)
cout<<" "<<ans[i]+;
cout<<endl;
return ;
}

CODEFORCES 125E MST Company 巧用Kruskal算法的更多相关文章

  1. CodeForces 125E MST Company

    E. MST Company time limit per test 8 seconds memory limit per test 256 megabytes input standard inpu ...

  2. POJ 1679 The Unique MST (次小生成树kruskal算法)

    The Unique MST 时间限制: 10 Sec  内存限制: 128 MB提交: 25  解决: 10[提交][状态][讨论版] 题目描述 Given a connected undirect ...

  3. MST最小生成树及克鲁斯卡尔(Kruskal)算法

    最小生成树MST,英文名如何拼写已忘,应该是min spaning tree吧.假设一个无向连通图有n个节点,那么它的生成树就是包括这n个节点的无环连通图,无环即形成树.最小生成树是对边上权重的考虑, ...

  4. HDU 2682 Tree(Kruskal算法求解MST)

    题目: There are N (2<=N<=600) cities,each has a value of happiness,we consider two cities A and ...

  5. HDU 5253 连接的管道(Kruskal算法求解MST)

    题目: 老 Jack 有一片农田,以往几年都是靠天吃饭的.但是今年老天格外的不开眼,大旱.所以老 Jack 决定用管道将他的所有相邻的农田全部都串联起来,这样他就可以从远处引水过来进行灌溉了.当老 J ...

  6. ZOJ 1586 QS Network(Kruskal算法求解MST)

    题目: In the planet w-503 of galaxy cgb, there is a kind of intelligent creature named QS. QScommunica ...

  7. POJ 1251 Jungle Roads(Kruskal算法求解MST)

    题目: The Head Elder of the tropical island of Lagrishan has a problem. A burst of foreign aid money w ...

  8. 最小生成树(MST)Prim算法和Kruskal算法

    刚学完最小生成树,赶紧写写学习的心得(其实是怕我自己忘了) 最小生成树概念:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边. 就是说 ...

  9. 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用

    图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...

随机推荐

  1. HDU 1540 POJ 2892 Tunnel Warfare

    线段树 区间合并 单点修改 区间查询.又是1秒钟构思,差错查了好久... ... 发现一个int型的定义成了char型,打脸. #include <stdio.h> #include &l ...

  2. astah* professional 6.9.0

    下载地址:http://members.change-vision.com/files/astah_professional/6_9_0 破解方法:按照Astah Professional 6.9后打 ...

  3. 三种Dataase Mapping的系统架构

    ORM - O/R M - Object/Relational Mapping: A technique/idea used to map objects and thier individual r ...

  4. df换行问题的设置

    df是linux下用来查磁盘空间的命令,而在使用了LVM分区或网络挂载的情况下,再用df取分区的使用率时,发现有些分区显示换行了,这样会导致通过脚本取的数据不对. [root@ ]# df -h Fi ...

  5. python函数的参数传递问题---传值还是传引用?

    摘要:在python中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是可以修改的对象.不可更改对象的传递属于传值,可更改对象属于传引用.想要在函数中传递 ...

  6. CSU 1515 Sequence

    莫队算法+map #include<cstdio> #include<cstring> #include<cmath> #include<map> #i ...

  7. java调用C/C++写的dll(转)

    源:java调用C/C++写的dll Java语言本身具有跨平台性,如果通过Java调用DLL的技术方便易用,使用Java开发前台界面可以更快速,也能带来跨平台性. Java调用C/C++写好的DLL ...

  8. 怎么把自己电脑上开发的项目发布到自己电脑IIS上面?

    windowsxp中: 步骤: 1.新建一个文件夹,把项目发布到里面(发布的时候需要注意的是: ) 注意:发布方法要选择:文件系统 目标位置选择:你新建来发布的那个文件夹名称 2.在IIS中新建网站 ...

  9. Tessnet2图片识别

    验证码识别据说可以用C#图像识别类库Tessnet2来实现,Tessnet2源于目前Google维护的开源项目Tesseract2.本文将对此传说进行验证,含验证结果与验证方法. 1. 验证结果 —— ...

  10. JDBC executeBatch 抛出异常停止

    进行批量更新的时候发现: addBatch(sql); executeBatch 抛出异常后,剩余的sql没有更新,即出现异常之前的都入库了,异常之后即使有可执行sql都不会执行. 百度资料后了解:这 ...