CSP 2018年12月 數據中心

題目描述

在這裏插入圖片描述

解題思路

一道很簡單的模板題,先求出該圖的最小生成樹
然後以root爲根節點每一層向下遍歷即可
按層向下遍歷需要小心,這裏使用的是鄰接表,生成最小生成樹的時候
是將其看爲無向圖,而現在是樹,從上往下意味着只能是單向傳輸
處理好這一點就沒有什麼問題了
代碼用的是一個set存MST的各個點,只要遍歷過就將其剝離

代碼如下

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<queue>
#include<set>

#define LOCAL
#define SEE(x) cout << #x << " : " << x << endl; 
using namespace std;

int n,m,root;
const int maxn = 50010;
int father[50010]; 
int rank[50010]; 
int used[50010];

struct edge
{
	int from;
	int to;
	int cost;
	edge(int from_ = 0,int to_ = 0,int cost_ = 0):from(from_),to(to_),cost(cost_){}
	bool operator < (edge other){ return cost < other.cost; }
};

vector<edge> edges;
vector<vector<pair<int,int> > > list(maxn);	// 存最後的最小生成樹的數據 鄰接表表示 
set<int> pointsSet;	// 存最後的節點的集合 


void init()
{
	for(int i = 0;i < maxn;i++) father[i] = i, rank[i] = 0, used[i] = 0;
}

int find(int x)
{
	return father[x] == x ? x : father[x] = find(father[x]);
}

void merge(int x,int y)
{
	x = find(x);
	y = find(y);
	if(x == y)  return;
	if(rank[x] < rank[y]) father[x] = y;
	else {
		father[y] = x;
		if(rank[x] == rank[y]) rank[x]++;
	}
}

// 按層遍歷 
int getRes(int root)
{
	int res = 0;
	vector<int> lastLayer;	// 記錄上一層的父節點 
	lastLayer.push_back(root);
	while(true)
	{
		if(lastLayer.size() == 0) break;
		vector<int> thisLayer = lastLayer;	// 當前層等於上一層 
		lastLayer.clear();
		int temp = 0;
		for(int i = 0;i < thisLayer.size();i++)
		{
			int node = thisLayer[i];
			pointsSet.erase(node);	// 以爲無向圖 1->2;2->1 只能有一個 
			for(int i = 0;i < list[node].size();i++)
			{
				int toNode = list[node][i].first; // 這一層的下一層節點
				// 如果已經使用過的節點就跳過 
				if(pointsSet.find(toNode) == pointsSet.end()) continue;
				// 如果這個點已經是這一條分支的最底層則不加入 
				if(list[toNode].size() != 1) lastLayer.push_back(toNode); 
				temp = max(temp,list[node][i].second);
			}
		}
		res = max(res,temp);
	}
	return res;
}


int main()
{
	init();
#ifdef LOCAL
	freopen("./in.txt","r",stdin);
#endif
	scanf("%d%d%d",&n,&m,&root);
	for(int i = 0;i < m;i++)
	{
		int beg,end,cost; scanf("%d%d%d",&beg,&end,&cost);
		edges.push_back(edge(beg,end,cost));
	}
	sort(edges.begin(),edges.end());
	for(int i = 0;i < m;i++)
	{
		edge temp = edges[i];
		if(find(temp.from) != find(temp.to))
		{
			merge(temp.from,temp.to);
			// 記錄最小生成樹的邊,有重複 
			list[temp.from].push_back(make_pair(temp.to,temp.cost));
			list[temp.to].push_back(make_pair(temp.from,temp.cost));
			// 加入MST點集 
			pointsSet.insert(temp.from);
			pointsSet.insert(temp.to);
		}
	}
	cout << getRes(root);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章