題目描述
解題思路
一道很簡單的模板題,先求出該圖的最小生成樹
然後以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;
}