Description
Input
Output
Sample Input
0.25 0.25 0.5
0 0.6 0.5
1 0 0
0.7 0.1 0.2
0.85 0.05 0.1
Sample Output
for(int k=0;k<nVertex;++k){
}
方法就是找到最小环上编号最大的点,最小环就是编号最大的点与其他两个点的连边再加上那两个点之间的最短路。Floyd最外层循环为k,即为枚举中间节点,在跑最短路之前,枚举i,j。
则:ans:=min(ans,dist[i][j]+graph[j][k]+graph[k][i])。
为什么呢?
Floyd要枚举中间节点,所以k不可能在i到j的最短路上,所以以上算法可以求得最小环
AC CODE
program
hy_1027;
const
eps=1e-
7
;
var
g,gg,dist:
array
[
1..500
,
1..500
]
of
longint
;
pp:
array
[
1..500
,
1..500
]
of
boolean
;
dx,dy,x,y:
array
[
1..500
]
of
double
;
p:
array
[
1..500
]
of
boolean
;
a:
array
[
1..500
]
of
longint
;
tot,i,j,k,ans,n,m:
longint
;
flag:
boolean
;
//============================================================================
function
min(a,b:
longint
):
longint
;
begin
if
a<b
then
min:=a
else
min:=b;
end
;
//============================================================================
function
right(g,h,k:
longint
):
boolean
; //判点是否在线的右边,用向量叉积的正负,同时要注
var
s:
double
; 意是否在线上。
begin
s:=(dx[h]-dx[g])*(y[k]-dy[g])-(x[k]-dx[g])*(dy[h]-dy[g]);
if
s<-eps
then
right:=
true
else
if
(
abs
(s)<eps)
and
(
abs
(
abs
(dx[h]-x[k])+
abs
(x[k]-dx[g])-
abs
(dx[g]-dx[h]))<eps)
then
right:=
true
else
right:=
false
;
end
;
//============================================================================
begin
readln(m,n);
for
i:=
1
to
m
do
readln(dx[i],dy[i]);
for
i:=
1
to
n
do
readln(x[i],y[i]);
fillchar(p,sizeof(p),
0
);
for
i:=
1
to
m
do
for
j:=
1
to
m
do
gg[i,j]:=
100000
;
for
i:=
1
to
m
do
for
j:=
1
to
m
do
begin
flag:=
true
;
for
k:=
1
to
n
do
if
((i<>j)
and
not
(right(i,j,k)))
or
((i=j)
and
((dx[i]<>x[k])
or
(dy[i]<>y[k])))
then //要判断只用一个提供的合金就可以的满足条件的情况。
begin
flag:=
false
;
break;
end
;
if
flag
then
begin
gg[i,j]:=
1
; p[i]:=
true
; p[j]:=
true
;
pp[i,j]:=
true
; //删掉没用的点。
end
;
end
;
tot:=
0
;
for
i:=
1
to
m
do
if
p[i]
then
begin
inc(tot);
a[i]:=tot;
end
;
for
i:=
1
to
tot
do
for
j:=
1
to
tot
do
g[i,j]:=
100000
;
for
i:=
1
to
m
do
for
j:=
1
to
m
do
if
pp[i,j]
then
g[a[i],a[j]]:=gg[i,j];
ans:=
100000
;
for
k:=
1
to
tot
do //Floyd
for
i:=
1
to
tot
do
for
j:=
1
to
tot
do
g[i,j]:=min(g[i,j],g[i,k]+g[k,j]);
for
i:=
1
to
tot
do //找最小环
for
j:=
1
to
tot
do
if
(i<>j)
and
(g[i,j]+g[j,i]<ans)
then
ans:=g[i,j]+g[j,i]
else
if
(i=j)
and
(g[i,j]<ans)
then
ans:=g[i,j];
if
ans=
100000
then
writeln
(
'-1'
)
else
writeln
(ans);
end
.