在线评测:
http://codevs.cn/problem/1069/
整体思路:
首先看到了题,我们的思路很简单,尽可能的去规避怨恨较大的案件,于是将关系按照影响坏的程度排序,并利用补集思想,将一个关系中的a,b两人
a与b的补集merge,b与a的补集merge。(这里我们开双倍数组,用sz[n+a] 来表示a的补集)不断的由大到小,当判断两个人已经同时存在于同意集合时,
即输出当前关系的影响,并return0;
失误之处:
1、没有考虑到结果为0的情况....
2、开始在将b与a merge的时候仅仅将a的fa接到了b的祖先上,而不是将a的祖先接到了b的祖先上,导致了集合判断的比较异常,WA了8个点
3、并查集的size初值填成了0,导致无论怎么加都是0,(多么蠢的事情,,,随便搞一个不大的正数就好了.....)
并查集那么简单,然而经常写错,所以来一份代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
struct
jd
{
int
x;
int
size;
};
jd fa[6000];
int
getfa(
int
x)
{
if
(fa[x].x == x)
return
x;
return
fa[x].x = getfa(fa[x].x);
}
void
merge(
int
x,
int
y)
{
int
s1 = fa[getfa(x)].size,s2 = fa[getfa(y)].size;
if
(s1 < s2)
{
fa[getfa(x)].x = getfa(y);
fa[getfa(y)].size += s1;
}
else
{
fa[getfa(y)].x = getfa(x);
fa[getfa(x)].size += s2;
}
}
|
体会心得:
1、常用的算法不要出现细节问题!!!!
2、全面考虑题意的结果!!
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
|
#include
#include
#include
#include
struct
lx
{
int
fa,sz;
};
struct
lx1
{
int
a, b, w;
};
lx sz[300000];
lx1 jl[300000];
int
n,m;
int
getfa(
int
x)
{
if
(sz[x].fa == x)
return
x;
return
sz[x].fa = getfa(sz[x].fa);
}
void
merge(
int
x,
int
y)
{
int
s1 = sz[getfa(x)].sz,s2 = sz[getfa(y)].sz;
if
(s1 > s2)
{
sz[getfa(x)].fa = getfa(y);
sz[getfa(y)].sz += s1;
}
else
{
sz[getfa(y)].fa = getfa(x);
sz[getfa(x)].sz += s2;
}
}
void
ycl()
{
for
(
int
i = 1;i <= 300000;i++)
{
sz[i].fa = i;
sz[i].sz = 1;
}
}
bool
pd(lx1 a,lx1 b)
{
if
(a.w > b.w)
return
true
;
return
false
;
}
using
namespace
std;
int
main()
{
ycl();
scanf
(
"%d%d"
,&n,&m);
for
(
int
i = 1;i <= m;i++)
{
scanf
(
"%d%d%d"
,&jl[i].a,&jl[i].b,&jl[i].w);
}
sort(jl+1,jl+m+1,pd);
for
(
int
i = 1;i <= m;i++)
{
if
(getfa(jl[i].a) == getfa(jl[i].b))
{
printf
(
"%d\n"
,jl[i].w);
return
0;
}
sz[getfa(jl[i].a)].fa = getfa(jl[i].b + n);
sz[getfa(jl[i].b)].fa = getfa(jl[i].a + n);
}
printf
(
"0\n"
);
return
0;
}
|