bzoj1706: [Usaco2007 Nov]relays 奶牛接力跑 (Floyd+新姿势)
2024-08-30 14:57:19
题目大意:有t(t<=100)条无向边连接两点,求s到e刚好经过n(n<=10^7)条路径的最小距离。
第一反应分层图,但是一看n就懵逼了,不会写。看了题解之后才知道可以这么玩。。。
首先有100条边最多200个点,但点编号到1000,所以离散化一下。
先把n转成2进制,按位考虑。dist[i][j][k]表示刚好经过2^i条边从j到k的最短距离,则dist[i,j,k]=min{dist[i-1][j][l]+dist[i-1][l][k]}。用类似快速幂的方法,若是2进制的n这一位是1的话,就把答案数组g和dist跑floyd(min{g[i-1][j][l]+dist[i-1][l][k]}),否则dist自己和自己跑(min{dist[i-1][j][l]+dist[i-1][l][k]}),这样子g就是跑n条路径得出的最小距离了。
代码如下:
type
map=array[..,..]of longint;
var
n,t,s,e,i,j,k,len,x,y,tot:longint;
c,d,g:array[..,..]of longint;
num:array[..]of longint; procedure merge(var a,b:map);
var
i,j,k:longint;
begin
fillchar(c,sizeof(c),);
for k:= to tot do
for i:= to tot do
for j:= to tot do
if c[i,j]>a[i,k]+b[k,j] then
c[i,j]:=a[i,k]+b[k,j];
a:=c;
end; procedure work;
begin
fillchar(g,sizeof(g),);
for i:= to tot do g[i,i]:=;
while n> do
begin
if n and = then merge(g,d);
merge(d,d);
n:=n>>;
end;
writeln(g[num[s],num[e]]);
end; begin
readln(n,t,s,e);
fillchar(d,sizeof(d),);
for i:= to t do
begin
readln(len,x,y);
if num[x]= then
begin
inc(tot);num[x]:=tot;
end;
if num[y]= then
begin
inc(tot);num[y]:=tot;
end;
d[num[x],num[y]]:=len;d[num[y],num[x]]:=len;
end;
work;
end.
最新文章
- 简单的例子了解自定义ViewGroup(一)
- 使用 expect 命令执行自动分发系统
- Atitit 常见的树形结构 红黑树 &#160;二叉树 &#160;&#160;B树 B+树 &#160;Trie树&#160;attilax理解与总结
- hdu 4496 (并差集)
- 在ecshop商品详情页显示供货商
- JavaScript之对象序列化详解
- DOM中元素对象的属性方法
- SpringMVC自定义配置消息转换器踩坑总结
- IntelliJ IDEA创建java项目
- 用C#语言编写:数组分析器
- python3爬虫之入门和正则表达式
- C# 添加Excel表单控件(Form Controls)
- node环境使用multer搭建一个图片接收服务器
- AJAX实现登陆
- 服务管理之rsync
- Codeforces Round #542 Div. 1
- Confluence 6 附件存储配置
- Java 构造器 遇到多个构造器时要考虑用构建器
- springboot-thymeleaf
- oracle 中decode函数用法