在线评测:
http://codevs.cn/problem/3287/
整体思路:
我们先看一下题,题中需要使道路上的边的最小值尽可能的大,而且并不关心距离之类的东西,保证尽可能的联通即可,所以我们来最大生成树。然后我们想一下,如在在一棵树上快速的求出两点间的路径的最小值,我们可以利用倍增lca来求,至于判断联通,则可以看两点的尽可能大的源点是否为同一个点,若不是,则不联通。
失误之处:
开始并查集忘记初始化了,并查集忘记初始化了,并查集忘记初始化了!!!!!md一直固定输出0,内心十分崩溃。、、
因为可能是森林,所以要保证每棵树的根节点的deep值相同,所以不要手贱的去给1号点单独赋个1的deep,,
体会心得:
做题时要认真,按照考试一样来认真对待,对于一些基础的东西,要心中有数,怎么写都不要出问题才行,同时一定要明白,我写这段代码究竟是在干什么,会有什么影响,会发生了么,不要想当然的去书写一些东西,
AC代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
struct lx
{
int x,y,w;
} sz[110000];
bool operator < (const lx &x,const lx &y)
{
return
x.w > y.w;
}
const int inf = 999999999;
int n,m,q,sum,a,b;
int head[20010],nxt[150000],to[150000],wei[150000];
int p[20010][32],fa[100000],size[100000];
int maxn[20010][32],deep[20010];
bool vis[20010];
void cr(int x,int y,int w)
{
sum++;
nxt[sum] = head[x];
head[x] = sum;
to[sum] = y;
wei[sum] = w;
}
int getfa(int x)
{
if
(fa[x] == x)
return
x;
return
fa[x] = getfa(fa[x]);
}
void merge(int x,int y)
{
int s1 = getfa(x),s2 = getfa(y);
if
(s1 == s2)
return
;
if
(size[s1] < size[s2])
{
fa[s1] = s2;
size[s2] += size[s1];
}
else
{
fa[s2] = s1;
size[s1] += size[s2];
}
}
void bcj_init()
{
for
(int i = 1;i <= n;i++)
fa[i] = i,size[i] = 1;
}
void zdscs()
{
sort(sz+1,sz+m+1);
for
(int i = 1;i <= m;i++)
{
if
(getfa(sz[i].x) != getfa(sz[i].y))
{
cr(sz[i].x,sz[i].y,sz[i].w);
cr(sz[i].y,sz[i].x,sz[i].w);
merge(sz[i].x,sz[i].y);
}
}
}
void dfs(int x)
{
vis[x] =
true
;
for
(int tp = head[x];tp;tp = nxt[tp])
{
if
(vis[to[tp]])
continue
;
deep[to[tp]] = deep[x] + 1;
p[to[tp]][0] = x;
maxn[to[tp]][0] = wei[tp];
dfs(to[tp]);
}
}
void plt()
{
for
(int i = 1;i <= n;i++)
{
if
(!vis[i])
{
p[i][0] = i;
dfs(i);
}
}
}
int l;
void init()
{
plt();
l = log2(n)+1;
for
(int i = 1;i <= l;i++)
{
for
(int j = 1;j <= n;j++)
{
p[j][i] = p[p[j][i-1]][i-1];
maxn[j][i] = min(maxn[j][i-1],maxn[p[j][i-1]][i-1]);
}
}
}
int lca(int a,int b)
{
if
(p[a][l] != p[b][l])
return
-1;
int ans = inf;
if
(deep[a] < deep[b]) swap(a,b);
int k = deep[a]-deep[b];
for
(int i = 0; i <= l;++i)
if
(k & (1<<i))
{
ans = min(ans, maxn[a][i]);
a = p[a][i];
}
if
(a == b)
return
ans;
for
(int j = l;j >= 0;j--)
{
if
(p[a][j] != p[b][j])
{
ans = min(ans, min(maxn[a][j], maxn[b][j]));
a = p[a][j];
b = p[b][j];
}
}
ans = min(ans, maxn[a][0]);
return
min(ans, maxn[b][0]);
}
int main()
{
scanf(
"%d%d"
,&n,&m);
for
(int i = 1;i <= m;i++)
{
scanf(
"%d%d%d"
,&sz[i].x,&sz[i].y,&sz[i].w);
}
bcj_init();
zdscs();
init();
scanf(
"%d"
,&q);
for
(int i = 1;i <= q;i++)
{
scanf(
"%d%d"
,&a,&b);
printf(
"%d\n"
,lca(a,b));
}
return
0;
}
|