首先,贴上一个很好的讲解贴:

http://www.wutianqi.com/?p=3012


HDOJ 1233 还是畅通工程

http://acm.hdu.edu.cn/showproblem.php?pid=1233

裸的Prim...

 #include<cstdio>
#define MAXN 105
#define INF 0x3f3f3f3f
int map[MAXN][MAXN];
int dist[MAXN];
int vis[MAXN];
int n,a,b,x,ans,tot;
void init()
{
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
{
if(i==j) map[i][j]=;
else map[i][j]=INF;
}
vis[i]=;
dist[i]=INF;
}
}
void Prim()
{
tot=;ans=;
for(int i=;i<=n;i++)
{
if(map[][i]<INF)
dist[i]=map[][i];
}
vis[]=;
int tmp,u=,flag;
for(int i=;i<=n;i++)
{
tmp=INF;flag=;
for(int j=;j<=n;j++)
{
if(!vis[j]&&dist[j]<tmp)
{
flag=;
tmp=dist[j];
u=j;
}
}
vis[u]=;
if(flag) ans+=dist[u];
for(int j=;j<=n;j++)
{
if(!vis[j]&&map[u][j]<dist[j])
dist[j]=map[u][j];
}
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
if(n==) break;
init();
for(int i=;i<n*(n-)/;i++)
{
scanf("%d%d%d",&a,&b,&x);
if(map[a][b]>x)//可能有重边,要取最小的,开始没加这个WA
{
map[a][b]=x;
map[b][a]=x;
}
}
Prim();
printf("%d\n",ans);
}
return ;
}

HDOJ 1863 畅通工程

http://acm.hdu.edu.cn/showproblem.php?pid=1863

遇见水题心情大好,哟哟切克闹,Kruskal、Prim各一套...

 #include<cstdio>
#include<queue>
#define MAXN 105
using namespace std;
int father[MAXN];
int find(int x)
{
return father[x]==x?x:father[x]=find(father[x]);
}
int merge(int a,int b)
{
int fa=find(a);
int fb=find(b);
if(fa!=fb)
{
father[fa]=fb;
return ;
}
return ;
}
struct line
{
int x,y,w;
friend bool operator<(line a,line b)
{
return a.w>b.w;
}
};
line tmp;
priority_queue<line> q;
int n,m,a,b,x,ans,tot;
int Kruskal()
{
tot=;
ans=;
while(!q.empty())
{
tmp=q.top();
q.pop();
if(merge(tmp.x,tmp.y))
{
tot++;
ans+=tmp.w;
if(tot==n-) return ;
}
}
return ;
}
void init()
{
for(int i=;i<=n;i++)
{
father[i]=i;
}
while(!q.empty()) q.pop();
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
if(m==) break;
init();
for(int i=;i<m;i++)
{
scanf("%d%d%d",&a,&b,&x);
tmp.x=a;
tmp.y=b;
tmp.w=x;
q.push(tmp);
}
if(Kruskal()) printf("%d\n",ans);
else printf("?\n");
}
return ;
}
 #include<cstdio>
#define MAXN 105
#define INF 0x3f3f3f3f
int map[MAXN][MAXN];
int dist[MAXN];
int vis[MAXN];
int n,m,a,b,x,ans,tot;
void init()
{
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
{
if(i==j) map[i][j]=;
else map[i][j]=INF;
}
dist[i]=INF;
}
}
int Prim()
{
ans=;
for(int i=;i<=n;i++)
{
if(map[][i]<INF)
dist[i]=map[][i];
vis[i]=;
}
vis[]=;
int tmp,u=;
for(int i=;i<=n;i++)
{
tmp=INF;
for(int j=;j<=n;j++)
{
if(!vis[j]&&dist[j]<tmp)
{
u=j;
tmp=dist[j];
}
}
if(vis[u]) return ;
vis[u]=;
ans+=tmp;
for(int j=;j<=n;j++)
{
if(!vis[j]&&map[u][j]<dist[j])
dist[j]=map[u][j];
}
}
return ;
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
if(m==) break;
init();
for(int i=;i<m;i++)
{
scanf("%d%d%d",&a,&b,&x);
if(map[a][b]>x)
{
map[a][b]=x;
map[b][a]=x;
}
}
if(Prim()) printf("%d\n",ans);
else printf("?\n");
}
return ;
}

HDOJ 1875 畅通工程再续

http://acm.hdu.edu.cn/showproblem.php?pid=1875

把int换成double就行了,还有用Prim比Kruskal好点 因为每条边都得算

 #include<cstdio>
#include<cmath>
#define INF 0x3f3f3f3f
#define MAXN 105
int point[MAXN][];//保存点的坐标
double map[MAXN][MAXN];//map矩阵
int vis[MAXN];//访问标记数组
double dist[MAXN];//没有加入到MST的点到MST的最短距离
int n,flag;
double ans;
double calc(int x1,int y1,int x2,int y2)
{
return sqrt((double)((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
}
int Prim()
{
ans=;
for(int i=;i<n;i++)
{
dist[i]=map[][i];
vis[i]=;
}
int u=;
double temp;
vis[]=;
for(int i=;i<n;i++)
{
temp=INF;
flag=;
for(int j=;j<n;j++)
{
if(!vis[j]&&dist[j]<temp)
{
u=j;
temp=dist[j];
flag=;
}
}
if(!flag) return ;
vis[u]=;
ans+=dist[u];
for(int j=;j<n;j++)
{
if(!vis[j]&&map[u][j]<dist[j])
dist[j]=map[u][j];
}
}
return ;
}
void create()
{
double tmp;
for(int i=;i<n;i++)
{
for(int j=i+;j<n;j++)
{
tmp=calc(point[i][],point[i][],point[j][],point[j][]);
if(tmp<10.0||tmp>1000.0)
{
map[i][j]=INF;
map[j][i]=INF;
}else
{
map[i][j]=tmp;
map[j][i]=tmp;
}
}
map[i][i]=0.0;
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=;i<n;i++)
{
scanf("%d%d",&point[i][],&point[i][]);
}
create();
if(Prim()) printf("%.1f\n", ans*);
else puts("oh!");
}
}

HDOJ 1879 继续畅通工程

http://acm.hdu.edu.cn/showproblem.php?pid=1879

对于已经建好的路  只需在建图时把边权赋为0  然后用Prim或者Kruskal求一棵MST即可

 #include<cstdio>
#define MAXN 105
#define INF 0x3f3f3f3f
int map[MAXN][MAXN];
int dist[MAXN];
int vis[MAXN];
int n,m,a,b,x,ans,tot,op;
void init()
{
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
{
if(i==j) map[i][j]=;
else map[i][j]=INF;
}
dist[i]=INF;
}
}
int Prim()
{
ans=;
for(int i=;i<=n;i++)
{
if(map[][i]<INF)
dist[i]=map[][i];
vis[i]=;
}
vis[]=;
int tmp,u=;
for(int i=;i<=n;i++)
{
tmp=INF;
for(int j=;j<=n;j++)
{
if(!vis[j]&&dist[j]<tmp)
{
u=j;
tmp=dist[j];
}
}
if(vis[u]) return ;
vis[u]=;
ans+=tmp;
for(int j=;j<=n;j++)
{
if(!vis[j]&&map[u][j]<dist[j])
dist[j]=map[u][j];
}
}
return ;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
if(n==) break;
init();
for(int i=;i<n*(n-)/;i++)
{
scanf("%d%d%d%d",&a,&b,&x,&op);
if(op==) x=;//已经建好的路 权值赋为0 然后求一棵MST即可
if(map[a][b]>x)
{
map[a][b]=x;
map[b][a]=x;
}
}
if(Prim()) printf("%d\n",ans);
else printf("?\n");
}
return ;
}

ZOJ 3204 Connect them

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3367

这题要求按最小的字典序输出最小生成树中的边的各个顶点...

在用Kruskal的时候,在边入优先队列的时候就得按照权值,x坐标,y坐标排序,

否则取得的最小生成树可能就是不符合题意的,这样在输出时候按照字典序输出了也是WA

 #include<cstdio>
#include<queue>
#include<algorithm>
#define INf 0x3f3f3f3f
#define MAXN 105
using namespace std;
// int map[MAXN][MAXN];
int father[MAXN];
int n,tot,a;
int find(int x)
{
return father[x]==x?x:father[x]=find(father[x]);
}
int merge(int a,int b)
{
int fa=find(a);
int fb=find(b);
if(fa!=fb)
{
father[fa]=fb;
return ;
}
return ;
}
struct line
{
int x,y,w;
friend bool operator<(line a,line b)//在找边时候同样权值的边也得按照字典序来取 开始没写后两行判断 WA数次...
{
if(a.w!=b.w)return a.w>b.w;
else if(a.x!=b.x)return a.x>b.x;
else return a.y>b.y;
}
};
line print[];
line tmp;
priority_queue<line> q;
void Kruskal()
{
tot=;
while(!q.empty())
{
tmp=q.top();
q.pop();
if(merge(tmp.x,tmp.y))
{
print[tot++]=tmp;
}
}
}
void init()
{
for(int i=;i<=n;i++)
{
father[i]=i;
}
while(!q.empty()) q.pop();
}
bool cmp(line a,line b)
{
if(a.x==b.x) return a.y<b.y;
else return a.x<b.x;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
init();
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
{
scanf("%d",&a);
if(a!=&&i<j)
{
tmp.x=i;
tmp.y=j;
tmp.w=a;
q.push(tmp);
}
}
}
Kruskal();
if(tot==n-)
{
sort(print,print+n-,cmp);
for(int i=;i<n-;i++)
{
printf("%d %d ", print[i].x,print[i].y);
}
printf("%d %d\n", print[n-].x,print[n-].y);
}else
{
printf("-1\n");
}
}
}

POJ 2349 Arctic Network

http://poj.org/problem?id=2349

这题有点难度,关键是分析出问题的本质...

要求任意两个不用卫星连通的城市之间的距离不超过d,则d越小,这个图被分成的连通块数量越多,卫星的数量就是连通块的数量-1

所以要求的d是一个恰好使这个图分成k+1个连通分量的一个最小值...

然后有这么一个定理:一个值能把这个图分成k个连通分量,则肯定能把这个图的最小生成树分成k个连通分量...

亦即 求最小生成树中的第K长边,可以想到Kruskal用的就是每次加入一条最小边的贪心法形成一棵MST

最小生成树共有n-1条边,第k长边,也就是Kruskal加入的第(n-k)条边,问题得解...具体见代码

 #include<cstdio>
#include<queue>
#include<cmath>
#define MAXN 550
// #define INF 0x3f3f3f3f
using namespace std;
int k,n,cnt;
int father[MAXN];
int find(int x)
{
return father[x]==x?x:father[x]=find(father[x]);
}
int merge(int a,int b)
{
int fa=find(a);
int fb=find(b);
if(fa!=fb)
{
father[fa]=fb;
return ;
}
return ;
}
struct edge
{
int x,y;
double w;
friend bool operator<(edge a,edge b)
{
return a.w>b.w;
}
};
edge tmp;
priority_queue<edge> q;
int point[MAXN][];
double clac(int x1,int y1,int x2,int y2)
{
return sqrt((double)((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
}
void add()
{
for(int i=;i<n;i++)
{
for(int j=i+;j<n;j++)
{
tmp.x=i;
tmp.y=j;
tmp.w=clac(point[i][],point[i][],point[j][],point[j][]);
q.push(tmp);
}
}
}
double Kruskal()
{
for(int i=;i<n;i++)
father[i]=i;
cnt=;
while(!q.empty())
{
tmp=q.top();
q.pop();
if(merge(tmp.x,tmp.y))
{
cnt++;
if(cnt==n-k) return tmp.w;//做了一点优化,找到第k长边就返回,快了大概200ms
}
}
return ;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
while(!q.empty()) q.pop();
scanf("%d%d",&k,&n);
for(int i=;i<n;i++)
{
scanf("%d%d",&point[i][],&point[i][]);
}
add();
printf("%.2f\n",Kruskal());
}
return ;
}

持续更新中...

MST最小生成树的更多相关文章

  1. [BZOJ1937][SHOI2004]Mst最小生成树(KM算法,最大费用流)

    1937: [Shoi2004]Mst 最小生成树 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 802  Solved: 344[Submit][Sta ...

  2. 【BZOJ1937】[Shoi2004]Mst 最小生成树 KM算法(线性规划)

    [BZOJ1937][Shoi2004]Mst 最小生成树 Description Input 第一行为N.M,其中 表示顶点的数目, 表示边的数目.顶点的编号为1.2.3.…….N-1.N.接下来的 ...

  3. [poj1679]The Unique MST(最小生成树)

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 28207   Accepted: 10073 ...

  4. UVA 1151 Buy or Build (MST最小生成树,kruscal,变形)

    题意: 要使n个点之间能够互通,要使两点直接互通需要耗费它们之间的欧几里得距离的平方大小的花费,这说明每两个点都可以使其互通.接着有q个套餐可以选,一旦选了这些套餐,他们所包含的点自动就连起来了,所需 ...

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

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

  6. MST最小生成树及Prim普鲁姆算法

    MST在前面学习了Kruskal算法,还有一种算法叫做Prim的.这两者的区别是Prim算法适合稠密图,比如说鸟巢这种几乎所有点都有相连的图.其时间复杂度为O(n^2),其时间复杂度与边的数目无关:而 ...

  7. 【KM】BZOJ1937 [Shoi2004]Mst 最小生成树

    这道题拖了好久因为懒,结果1A了,惊讶∑( 口 || [题目大意] 给定一张n个顶点m条边的有权无向图.现要修改各边边权,使得给出n-1条边是这张图的最小生成树,代价为变化量的绝对值.求最小代价之和. ...

  8. Prim求MST最小生成树

    最小生成树即在一个图中用最小权值的边将所有点连接起来.prim算法求MST其实它的主要思路和dijkstra的松弛操作十分相似 prim算法思想:在图中随便找一个点开始这里我们假定起点为“1”,以点1 ...

  9. 【BZOJ2238】Mst 最小生成树+LCA+堆

    [BZOJ2238]Mst Description 给出一个N个点M条边的无向带权图,以及Q个询问,每次询问在图中删掉一条边后图的最小生成树.(各询问间独立,每次询问不对之后的询问产生影响,即被删掉的 ...

随机推荐

  1. C++实现两个大整数的相加(考虑到负数异常情况)

    实现两个大整数的相加,首先应该排除直接使用int和long long的方法,这些方法很容易溢出,这里为了方便(是否可以使用更精简的结构存储?)采用char来存储整数,整体思路如下: 1. 对于整数n和 ...

  2. Python【关联接口的开发】

    import flask,time,json,hashlib,redis print("==============被调函数部分================")def my_m ...

  3. 又一家药企IPO被拒,原因竟然是……

    版权所有,未经授权不得转载,QQ:231469242 导读 近日,中国证监会官网发布公告,河南润弘制药首发未IPO能通过,成为今年第4家IPO被否的制药企业.中国证监会拒绝润弘制药的原因是润弘制药产品 ...

  4. 容斥 或者 单调栈 hihocoder #1476 : 矩形计数 和 G. Snake Rana 2017 ACM Arabella Collegiate Programming Contest

    先说一个简单的题目(题目大意自己看去,反正中文):hihocoder上的:http://hihocoder.com/problemset/problem/1476 然后因为这个n和m的矩阵范围是100 ...

  5. C++ Core Guidelines

    C++ Core Guidelines September 9, 2015 Editors: Bjarne Stroustrup Herb Sutter This document is a very ...

  6. windows下自动启动Redis隐藏命令行窗口

    这段时间看了看关于Redis的相关内容,对于Redis在windows下的安装和常规启动我就不多说了.可以参考其他的博客http://www.cnblogs.com/edisonchou/p/3821 ...

  7. javamail模拟邮箱功能--邮件回复-中级实战篇【邮件回复方法】(javamail API电子邮件实例)

    引言: JavaMai下载地址l jar包:http://java.sun.com/products/javamail/downloads/index.html 此篇是紧随上篇文章而封装出来的,阅读本 ...

  8. WPF让人哭笑不得的BUG

    前几天遇到了一个让我哭笑不得的bug,我写的Wpf程序在Win7里可以运行,到XP.WindowsServer里运行点击某个控件之后闪退,不报任何错,在后台代码里trycatch也捕捉不到任何异常.很 ...

  9. SpringCloud之Eureka(注册中心集群篇)

    一:集群环境搭建 第一步:我们新建两个注册中心工程一个叫eureka_register_service_master,另一个叫eureka_register_service_backup eureka ...

  10. SolrJ查询条件组合查询实现——(十六)

    带查询条件的实现原理: 查询按钮被包在一个大表单,表单还有三个隐藏域,一个商品筛选,一个 价格,一个排序,每次点击查询时候清空三个隐藏域,就带着一个大条件去查询;点击下面的筛选条件时,给隐藏域的筛选条 ...