关于这个东西,有的童鞋又要开始蒙了,最小生成树是个什么鬼?!
前面我们已经说过树是什么东西了,所谓最小生成树嘛,最小嘛,那就是所有生成的树中最小的那个呗!
太别扭了对吧?
好,我们来看看官方回答。
一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。
prim算法
#include<bits/stdc++.h>
using namespace std;
const int maxn=10010;
int n,m,edge[maxn][maxn];
int dis[maxn];
bool boo[maxn];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
edge[x][y]=edge[y][x]=z;
}
dis[1]=0;
boo[1]=true;
for(int i=2;i<=n;++i)
dis[i]=123456789;
for(int i=2;i<=n;++i)
if(edge[1][i])
dis[i]=min(dis[i],edge[1][i]);
int ans=0;
for (int i=1;i<=n-1;++i)
{
int maxd=0;
for(int j=1;j<=n;++j)
{
if(!boo[j])
if(maxd==0||dis[maxd]>dis[j])
maxd=j;
}
boo[maxd]=true;
ans+=dis[maxd];
for(int j=1;j<=n;++j)
{
if(!boo[j])
if(edge[maxd][j])
dis[j]=min(dis[j],edge[maxd][j]);
}
}
printf("%d\n",ans);
return 0;
}
是不是感觉k算法比p算法好理解啊(暂且先那么叫)
据徐大佬说k算法好像比p算法快,唉,如果让你写的话,是不是一定选择这种又快有好写还有好理解的代码啊。
反正让我写的的话,我一定会选择写k算法的,但是这仅限于裸地最小生成树的题。
对于有的题k算法是不如p算法的,甚至有的时候,你用k算法还不一定能做出来。
好了,废话不多说了,我们来看看代码吧。
#include <bits/stdc++.h> using namespace std; const int maxn=100000+15; struct Edge { int x,y,z; }edge[maxn]; bool cmp(Edge a,Edge b) { return a.z<b.z; } int top[maxn],x,y,z,n,m; int found(int x) { if (top[x]==x) return x; top[x]=found(top[x]); return top[x]; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); edge[i].x=x; edge[i].y=y; edge[i].z=z; } sort(edge+1,edge+m+1,cmp); for (int i=1;i<=n;i++) top[i]=i; int ans=0; for (int i=1;i<=m;i++) { int x=edge[i].x,y=edge[i].y; int fx=found(x),fy=found(y); if (fx==fy) continue; top[fx]=fy; ans+=edge[i].z; } printf("%d\n",ans); return 0; }
最小瓶颈生成树
有的童鞋看到这个就要抓狂了,这又是个什么鬼!!!
哎呀,不要着急,我们来具体看一看这个东西。
最小瓶颈生成树:在一个图中找出一棵树,使这棵树的最大权值最小。
给你一个这样的关系吧:最小生成树一定是最小瓶颈生成树,最小瓶颈生成树不一定是最小生成树。
最优比率生成树
#include <bits/stdc++.h> using namespace std; const int maxn=100000+15; struct Edge { int x,y,a,b; Edge(int x=0,int y=0,int a=0,int b=0): x(x),y(y),a(a),b(b) {} }edge[maxn],edge2[maxn]; int mst() { return 0; } int change(int K) { for (int i=1;i<=m;i++) edge2[i]=Edge(edge[i].x,edge[i].y, edge[i].a-K*edge[i].b,0); return 0; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { int x,y,a,b; scanf("%d%d%d%d",&x,&y,&a,&b); edge[i]=Edge(x,y,a,b); } int l=0,r=1000000,mid; while (l+1<r) { mid=(l+r)/2; change(mid); if (mst()<=0) r=mid; else l=mid; } printf("%d\n",r); return 0; }