具体题目就不贴了。
不得不说这是一道非常吓人的题。
解题思路:审题有些难度,第一眼看到这道题有些吓人,细细分析(AC )后发现其实不难。题目中希望求出一个最优的树结构传输图,也就是一个最大传输时间最小的树。接下来来看对最大传输时间
T
m
a
x
T_{max}
Tmax的定义:
T
m
a
x
T_{max}
Tmax是树中每层的最大传输时间的最大值。
结合上面的图可以看出,
T
m
a
x
=
m
a
x
{
T
1
,
T
2
,
T
3
.
.
.
}
T_{max}=max{\{T_1,T_2,T_3...\}}
Tmax=max{T1,T2,T3...},树的每一层中
T
i
=
m
a
x
{
t
i
,
1
,
t
i
,
2
,
t
i
,
3
,
t
i
,
4
.
.
.
.
}
T_i=max{\{t_{i,1},t_{i,2},t_{i,3},t_{i,4}....\}}
Ti=max{ti,1,ti,2,ti,3,ti,4....},要使得
T
m
a
x
T_{max}
Tmax最小,也就是要让选入连接各个点的边的传输时间(
t
i
,
j
t_{i,j}
ti,j)的最大值最小,同时要使得整个树的节点都能传输数据到root(可以理解为整个树必须是联通的),此处我认为给出的root没什么用,因为即使root改变了,也就是说将树中的某个子节点看作根节点,它仍然满足树结构,并且树中的边没有变则
T
m
a
x
T_{max}
Tmax的值就不会改变。
解题步骤:将边按传输时间排序,依次选边,选的过程中注意不能产生环,直到整个树联通,选的最后一条边的传输时间即为
T
m
a
x
T_{max}
Tmax,也就是扩边法求最小生成树的思路。
100分代码(虽然100分,但是还是很虚,毕竟还是刷了好几年的真题了,还真没见过这样的第四题,思路有什么不对的地方还请各位指正。)
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <sstream>
#include <cstring>
#include <iterator>
#include <set>
#include <map>
using namespace std;
typedef struct edge
{
int u,v,len;
}edge;
int par[100005];
void init(int n)
{
for(int i = 0;i <= n; i++)
par[i] = i;
}
int find(int k)
{
if(k == par[k])
return k;
else
return par[k] = find(par[k]);
}
bool same(int i,int j)
{
return find(i) == find(j);
}
void unite(int i,int j)
{
i = find(i);
j = find(j);
if(i == j)
return ;
else
par[i] = j;
}
bool cmp(edge& a,edge& b)
{
return a.len < b.len;
}
int solve(int n,vector<edge>& G)
{
int ans = 0,cnt = 0;
init(n);
int mark[n];
memset(mark,0,sizeof(mark));
sort(G.begin(),G.end(),cmp);
for(int i = 0;i < G.size(); i++)
{
if(!same(G[i].u,G[i].v))
{
unite(G[i].v,G[i].u);
ans = G[i].len;
if(mark[G[i].u] == 0)
{
cnt++;
mark[G[i].u] = 1;
}
if(mark[G[i].v] == 0)
{
cnt++;
mark[G[i].v] = 1;
}
if(cnt == n)
return ans;
}
}
return ans;
}
int main(int argc, char const *argv[])
{
int n,m,root;
cin >> n >> m;
vector<edge> G(m);
cin >> root;
for(int i = 0;i < m; i++)
cin >> G[i].u >> G[i].v >> G[i].len;
cout << solve(n,G) << endl;
return 0;
}