1. 程式人生 > 資訊 >京東方 OLED 螢幕前三季度出貨近 4000 萬塊,重慶生產線也已投產

京東方 OLED 螢幕前三季度出貨近 4000 萬塊,重慶生產線也已投產

最小生成樹(MST)

對於稀疏圖:

1、樸素Prim演算法 時間複雜度\(O(n^2)\)

演算法分析:和樸素Dijkstra的演算法流程十分相似,定義集合S表示最小生成樹的集合,每次先找出集合外距離集合最近的點t,隨後再用t去更新其他點到集合的距離。
https://www.acwing.com/problem/content/860/
程式碼示例:

//#pragma comment(linker,   "/STACK:10240000000000,10240000000000")
//#pragma GCC optimize(2)

#include <bits/stdc++.h>
using namespace std;

#define For(i,a,b) for (int i=(a);i<=(b);++i)
#define Fod(i,b,a) for (int i=(b);i>=(a);--i)
#define mls multiset
#define lb lower_bound
#define ub upper_bound
#define pb push_back
#define pob pop_back
#define itt iterator
#define endl '\n'
#define IOS ios::sync_with_stdio(0); cin.tie(0);
#define lowbit(x) x & (-x)
#define clr(x) memset(x, 0, sizeof(x));
#define fi first
#define se second

typedef vector<int> vii;
typedef vector<long long> vll;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
		
const int MAXN = 0x3f3f3f3f;
const int MOD = 1000000007;
const ll MOD1 = 212370440130137957ll;

const int N = 505;
const int M = 1e5 + 5;

int g[N][N];
int n, m;
int dist[N];
bool st[N];

int prim()
{
	memset(dist, 0x3f, sizeof dist);
	int res = 0;
	for(int i = 0; i < n; i ++)
	{
		int t = -1;
		for(int j = 1; j <= n; j ++)
			if(!st[j] && (t == -1 || dist[j] < dist[t])) t = j;
		if(i && dist[t] == MAXN) return MAXN;
		if(i) res += dist[t]; 
		st[t] = true;
		for(int j = 1; j <= n; j ++) //儲存完dist[t]的值之後再去更新,以防出現自環的情況
			dist[j] = min(dist[j], g[t][j]);
	}
	return res;
}

int main ()
{	
	//IOS;
	cin >> n >> m;
	memset(g, 0x3f, sizeof g);
	for(int i = 1; i <= m; i ++)
	{
		int a, b, c;
		cin >> a >> b >> c;
		g[a][b] = g[b][a] = min(g[a][b], c);
	}

	int t = prim();
	if(t == MAXN) puts("impossible");
	else cout << t << endl;

	return 0;
}	
/*

*/	

對於稠密圖:

1、Kruskal演算法 時間複雜度\(O(mlogm)\)

演算法分析:先將每個點看作一棵獨立分離的樹,之後先將所有邊按邊權從小到大進行排序,然後遍歷每條邊進行兩點的相連,若兩點連通則相連,否則不連,判斷方式可以用並查集。最終當連的邊數為n-1條時,即存在最小生成樹(所有點皆連通),過程中再用個res記錄下每條連線的邊的邊權和即可
https://www.acwing.com/problem/content/861/
程式碼示例:

//#pragma comment(linker,   "/STACK:10240000000000,10240000000000")
//#pragma GCC optimize(2)

#include <bits/stdc++.h>
using namespace std;

#define For(i,a,b) for (int i=(a);i<=(b);++i)
#define Fod(i,b,a) for (int i=(b);i>=(a);--i)
#define mls multiset
#define lb lower_bound
#define ub upper_bound
#define pb push_back
#define pob pop_back
#define itt iterator
#define endl '\n'
#define IOS ios::sync_with_stdio(0); cin.tie(0);
#define lowbit(x) x & (-x)
#define clr(x) memset(x, 0, sizeof(x));
#define fi first
#define se second

typedef vector<int> vii;
typedef vector<long long> vll;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
		
const int MAXN = 0x7fffffff;
const int MOD = 1000000007;
const ll MOD1 = 212370440130137957ll;

const int M = 2e5 + 5;
const int N = 1e5 + 5;
struct node
{
	int a, b, c;
	bool operator < (const node &x) const
	{
		return c < x.c;
	}
}e[M];
int n, m; 
int p[N];
int res;
int cnt;
int find(int x)
{
	if(x == p[x]) return x;
	return p[x] = find(p[x]);
}

int main ()
{	
	//IOS;
	cin >> n >> m;
	for(int i = 1; i <= m; i ++)
	{
		int a, b, c;
		cin >> a >> b >> c;
		e[i] = {a, b, c};
	}
	sort(e + 1, e + 1 + m);
	for(int i = 1; i <= n; i ++)  p[i] = i;
	for(int i = 1; i <= m; i ++)
	{
		int a = find(e[i].a), b = find(e[i].b);
		if(a != b)
		{
			p[b] = a;
			res += e[i].c;
			cnt ++;
		}
	}
	if(cnt != n - 1) puts("impossible");
	else cout << res << endl;
	return 0;
}	

PS:而對於堆優化版的Prim演算法其實和堆優化Dijkstra一樣,但演算法實現上不如kruskal簡單,且時間複雜度差不多,因此不常用。