您的位置:首页 > 其它

模板整理: 图论---最小生成树

2017-11-09 16:40 489 查看
最小/大生成树是个非常厉害的知识点,

题目可以出得很巧,

记住它的最优子结构性质,并且很多时候性质有大用(例如货车运输)

稀疏图Kruskal,稠密图(有时候)Prim.

求最小生成树一般都是2种:

1.prim

O(N2),可以用堆优化到O(N∗log(N)),

不是很常用,不过其实也很好写。

好吧也不能说不常用,我是指我用得比较少= =

毕竟C++一个sort就可以做Kruskal了。

还有啥啥fib堆优化prim的就随风远去吧。

//这是个O(n^2)的prim
//Map[i][j]表示i到j边的权值
//注意初始化vis(如果你要多次运行这个的话)
int Prim(){
int ans=0;
for (int i=1;i<=n;i++) dis[i]=Map[1][i];
vis[1]=1;
for (int i=1;i<n;i++){
int Min=inf,mi=0;
for (int j=1;j<=n;j++)
if (!vis[j] && Min>dis[j]) Min=dis[j],mi=j;
vis[mi]=1;
ans=max(ans,Min);
for (int j=1;j<=n;j++)
if (dis[j]>Map[mi][j]) dis[j]=Map[mi][j];
}
return ans;
}


2.Kruskal

把边排序然后贪心。

好写而且一般都挺快的(除非边真的多)

还可以结合高级数据结构做些事体(=v= bzoj3669)

//Edge是输入的边,这些是准备部分
struct Edge{
int L,R,num;
}E[M];
bool cmp(Edge x,Edge y){
return x.num<y.num;
}
int getfa(int x){
if (fa[x]!=x) fa[x]=getfa(fa[x]);
return fa[x];
}  //并查集
bool unn(int x,int y){
int t1=getfa(x),t2=getfa(y);
if (t1==t2) return 1;
else{
fa[t2]=t1;
return 0;
}
}  //合并x和y,并且如果x和y已经一起返回1,不然返回0

//这是主程序里的内容,tot为边数,n为点数,E是Edge类型
sort(E+1,E+1+tot,cmp);
for (int i=0;i<=n;i++) fa[i]=i;
int ans=0; //答案统计
for (int i=1;i<=tot;i++){
if (unn(E[i].L,E[i].R)) continue;
ans+=E[i].num;
}


还有个平面图最小生成树,BFS处理的,

不会考,那么模板先这样了,

主要是会去用,本质是dp(写法是贪心)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: