最小生成树

生成树

无向图的某个子图中任意两个顶点都能互相联通且是一棵树

一个连通图的生成树是指一个连通子图,它含有图中全部n个顶点,但只有足以构成一棵树的n-1条边。一颗有n个顶点的生成树有且仅有n-1条边,如果生成树中再添加一条边,则必定成环。

BFS生成树

连通图的BFS生成树:
n个顶点,n-1条边;

特点:

  • 不存在回路;
  • 少任何边都不连通;
  • 加入原图的任何边,都会产生回路。
DFS生成树

连通图的DFS生成树:
n个顶点,n-1条边;

– 特点:

  • 不存在回路;
  • 少任何边都不连通;
  • 加入原图的任何边,
    都会产生回路。
最小生成树

边上权和最小的生成树

具体可以参考这篇

Prim算法

O(|E|log|V|)

从任意一个顶点开始,每次选择一个与当前顶点集最近的一个顶点(边权最小),并将两顶点之间的边加入到树中。

int cost[maxn][maxn];
int mincost[maxn];
int vis[maxn];
int n;

int prim() {

	for (int i=0; i<n; i++) {
		mincost[i]=INF;
		vis[i]=0;
	}
	mincost[0]=0;
	int ans=0;
	while (1) {
		int v=-1;
		for (int i=0; i<n; i++) {
			if (!vis[i] && (v==-1 || mincost[i]<mincost[v]))
				v=i;
		}
		if (v==-1) break;
		vis[v]=1;
		ans+=mincost[v];
		for (int i=0; i<n; i++)
			mincost[i]=min(mincost[i], cost[v][i]);
	}
	return ans;
}
Kruskal算法

O(|E|log|V|)

按边权值顺序从小到大看一遍,如果不产生圈就把当前边加入生成树。

struct edge {
	int u,v;
	ll cost;
}es[maxn*maxn];
//edge path[maxn*maxn];
int par[maxn];
int ran[maxn];
int n;
int cnt=0;
//int num=0;
bool cmp(const edge& e1, const edge& e2){
	return e1.cost<e2.cost;
}

void init() {
	for (int i=0; i<=n; i++) {
		par[i]=i;
		ran[i]=0;
	}
}

int find(int root) {
	while (root!=par[root])
		root=par[root];
	return root;
}

void unite(int x, int y) {
	x=find(x);
	y=find(y);
	if (x==y) return;
	if (ran[x]<ran[y]) par[x]=y;
	else {
		par[y]=x;
		if (ran[x]==ran[y]) ran[x]++;
	}
}


bool same(int x, int y) {
	return find(x)==find(y);
}


ll kruskal() {
	sort(es,es+cnt,cmp);
	init();
	ll ans=0;
	for (int i=0; i<cnt; i++) {
		edge e=es[i];
		if (!same(e.u,e.v)) {
			unite(e.u,e.v);
			ans+=e.cost;
			//path[num].u=e.u;
			//path[num++].v=e.v; 可记录路径 
		}
	}
	return ans;
}

void addedge(int i, int j, int w){
	if (w!=0) {
		es[cnt].u=i;
		es[cnt].v=j;
		es[cnt++].cost=w;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值