zoukankan      html  css  js  c++  java
  • 最小生成树

    定义

    • 在无向图中 生成一棵树,这棵树涵盖所有顶点,且权值之和最小

    性质

    • 边数=n-1
    • 对于给定的图,最小生成树可能不唯一,但是权值之和一定唯一
    • 每一个结点都是平等的(因为来源于图)
    • O(v2),可以用堆优化为O(VlogV+E)

    代码

    邻接矩阵

    #include<algorithm>
    using namespace std;
    const int max_n = 30;
    const int INF=0x3fffffff;
    int n,G[max_n][max_n];
    bool vis[max_n] = { false };
    int d[max_n];//距离集合的最短距离
    //prim算法
    //邻接矩阵
    void prim()
    {
    	fill(d, d + n, INF);
    	//选出
    	d[0] = 0;
    	for (int j = 0; j < n ;j++)
    	{
    		int u = -1, min = INF;
    		//选出最近的
    		for (int i = 0; i < n; i++)
    		{
    			if (vis[i] == false && d[i] < min)
    			{
    				min = d[i];
    				u = i;
    			}
    		}
    		//加入集合 更新
    		if (u == -1)return;
    		vis[u] = true;
    		for (int i = 0; i < n; i++)
    		{
    			if (vis[i] == false && G[u][i] != INF && d[i] > G[u][i])
    			{
    				d[i] = G[u][i];
    			}
    		}
    	}
    	
    }
    

    邻接表

    #include<algorithm>
    #include<vector>
    using namespace std;
    //最小生成树:在无向图中 生成一棵树,这棵树涵盖所有顶点,且权值之和最小
    //1.边数=n-1
    //2.对于给定的图,最小生成树可能不唯一,但是权值之和一定唯一
    //3.每一个结点都是平等的(因为来源于图)
    const int max_n = 30;
    const int INF=0x3fffffff;
    int n;
    struct  node
    {
    	int v;
    	int dis;
    };
    vector<node*>Adj[max_n];
    bool vis[max_n] = { false };
    int d[max_n];//距离集合的最短距离
    //prim算法
    //邻接表
    void prim()
    {
    	fill(d, d + n, INF);
    	d[0] = 0;
    	for (int j = 0; j < n - 1; j++)
    	{
    		int u = -1, min = INF;
    		for (int i = 0; i < n; i++)
    		{
    			if (vis[i] == false && d[i] < min)
    			{
    				min = d[i];
    				u = i;
    			}
    		}
    		if (u == -1)return;
    		vis[u] = true;
    		for (int i = 0; i < Adj[u].size(); i++)
    		{
    			int v = Adj[u][i]->v;
    			int dis = Adj[u][i]->dis;
    			if (vis[v] == false && d[v] > dis)
    			{
    				d[v] = dis;
    			}
    		}
    	}
    	
    }
    

    Kruskal算法

    • 加最小边 然后判断有没有环
    • 使用并查集 没有环:两个端点的根节点不同
    #include<algorithm>
    using namespace std;
    const int max_n = 30;
    const int max_e = 40;
    int father[max_n];
    int e,n;
    struct edge
    {
    	int s;
    	int d;
    	int dis;
    };
    edge edges[max_e];
    bool cmp(edge e1,edge e2)
    {
    	return e1.dis < e2.dis;
    }
    //找到根节点
    int findFather(int v)
    {
    	int x = v;
    	while (father[x] != x)
    	{
    		x = father[x];
    	}
    	return x;
    }
    //合并两个集合
    bool Union(int x, int y)
    {
    	int fx = findFather(x), fy = findFather(y);
    	if (fx != fy)
    	{
    		father[fy] = fx;
    		return true;
    	}
    	return false;
    }
    int kruskal()
    {
    	sort(edges, edges + e, cmp);
    	int ans = 0;//权值之和
    	int cnt = 0;//边数
    	for (int i = 0; i < n; i++)
    	{
    		father[i] = i;
    	}
    	for (int i = 0; i < e; i++)
    	{
    		if (Union(edges[i].s, edges[i].d))//判断有没有环
    		{
    			ans += edges[i].dis;//选择这条边
    			cnt++;
    		}
    		if (cnt == n - 1)
    		{
    			break;
    		}
    	}
    	
    	return ans;
    }
    
  • 相关阅读:
    Android Activity与Service的交互方式
    Android Service和Thread的区别
    Android Binder机制简单了解
    Android内的生命周期整理
    Android App的生命周期是什么
    ListView item 中TextView 如何获取长按事件
    Go之并发处理(售票问题)
    Go之简单并发
    Go之函数直接实现接口
    Go之类型判断
  • 原文地址:https://www.cnblogs.com/code-fun/p/15235861.html
Copyright © 2011-2022 走看看