题目连接:http://www.tyvj.cn/Problem_Show.aspx?id=1064
首先,因为士兵是瞬间到达的,而且不会因为距离的远近而花费代价,所以,如果我们要进行更改,那么必定改最优值!
而最优值就是最小生成树的权值和,我们用时间作为一层层的循环,用F[I]表示i结束后,最小用的代价为多少。
而每次推则是默认一段时间内,不发生改变,于是,得到下面的公式:
F[I]:=MIN{F[J]+try(j+1,i)} (0<=j<i)
try(l,r)表示在时刻l~r中,用不是灾难的边构建一棵最小生成树的代价。
这其中可以加许多小优化,就不多说了。
建议用Kruska算法求最小生成树,因为经过处理后,最小生成树的总时间代价为O(T*T*M+MLOGM)!!
code:
var
t1,t2,n,m,day,eat,change,i,j,x,y,z,dis:longint;
f:array[0..60] of int64;
a,b,c:array[0..10010] of longint;
fa:array[0..310] of longint;
g:array[0..310,0..310,0..60] of boolean;
flag:boolean;
l:array[0..20010] of boolean;
function get(x:longint):longint;
begin
if fa[x]<>x then fa[x]:=get(fa[x]);
exit(fa[x]);
end;
function work(k:longint):longint;
var
tot,ans,i,x,y:longint;
begin
for i:=1 to 2*m do
if g[a[i],b[i],k]=false then l[i]:=false;
for i:=1 to n do
fa[i]:=i;
ans:=0;
tot:=0;
for i:=1 to 2*m do
if l[i] then
begin
x:=0;
x:=get(a[i]);
y:=0;
y:=get(b[i]);
if x<>y then
begin
fa[x]:=y;
fa[a[i]]:=y;
ans:=ans+c[i];
tot:=tot+1;
end;
end;
if tot=(n-1) then exit(ans) else exit(-1);
end;
procedure sort(l,r: longint);
var
i,j,x,y: longint;
begin
i:=l;
j:=r;
x:=c[(l+r) div 2];
repeat
while c[i]<x do
inc(i);
while x<c[j] do
dec(j);
if not(i>j) then
begin
y:=a[i];
a[i]:=a[j];
a[j]:=y;
y:=b[i];
b[i]:=b[j];
b[j]:=y;
y:=c[i];
c[i]:=c[j];
c[j]:=y;
inc(i);
j:=j-1;
end;
until i>j;
if l<j then
sort(l,j);
if i<r then
sort(i,r);
end;
begin
read(n,m,day,eat,change);
for i:=1 to m do
begin
read(x,y,z);
a[i]:=x;
b[i]:=y;
c[i]:=z;
a[i+m]:=y;
b[i+m]:=x;
c[i+m]:=z;
end;
sort(1,m*2);
read(dis);
fillchar(g,sizeof(g),true);
for i:=1 to dis do
begin
read(x,y,t1,t2);
for j:=t1 to t2 do
g[x,y,j]:=false;
for j:=t1 to t2 do
g[y,x,j]:=false;
end;
f[0]:=0;
for i:=1 to day do
begin
flag:=false;
f[i]:=maxlongint;
fillchar(l,sizeof(l),true);
for j:=i-1 downto 0 do
begin
if flag or (j<0) then break;
x:=work(j+1);
if x=-1 then flag:=true
else
begin
x:=x*eat*(i-j)+change;
if (x+f[j])<f[i] then f[i]:=x+f[j];
end;
end;
end;
writeln(f[day]);
end.
下面是一组数据
10 45 30 3 600
1 2 106
1 3 192
1 4 48
1 5 104
1 6 148
1 7 117
1 8 47
1 9 30
1 10 145
2 3 5
2 4 127
2 5 12
2 6 45
2 7 36
2 8 6
2 9 24
2 10 40
3 4 172
3 5 123
3 6 63
3 7 191
3 8 91
3 9 85
3 10 27
4 5 134
4 6 158
4 7 43
4 8 130
4 9 155
4 10 124
5 6 38
5 7 89
5 8 171
5 9 157
5 10 138
6 7 107
6 8 151
6 9 41
6 10 139
7 8 7
7 9 167
7 10 119
8 9 177
8 10 83
9 10 130
10
4 6 19 20
5 1 27 28
4 7 6 12
5 3 1 10
8 4 13 28
7 1 7 12
6 8 5 16
2 3 11 21
2 5 11 17
8 2 8 28
答案是24153
本文探讨了在特定时间范围内的最小生成树问题,并利用Kruskal算法进行求解,通过时间作为循环变量,实现了最小代价的计算。文中详细介绍了F[I]表示法和try函数的作用,以及如何在时间约束下构建最小生成树。此外,还提供了优化策略和代码实现,最终通过一组数据验证了解决方案的有效性。
586

被折叠的 条评论
为什么被折叠?



