【BZOJ】【1046】/【POJ】【3613】【USACO 2007 Nov】Cow Relays 奶牛接力跑
倍增+Floyd
题解:http://www.cnblogs.com/lmnx/archive/2012/05/03/2481217.html
神题啊= =Floyd真是博大精深……
题目大意为求S到E,恰好经过N条边的最短路径(姑且称为路径吧,虽然好像已经不是了……)
总共只有大约200个点(很多点根本没走到,离散化一下即可)所以可以考虑Floyd算最短路。
引用下题解:
题目求i,j之间边数恰为N的最短路径(边可以重复走),我们知道线性代数中有:01邻接矩阵A的K次方C=A^K,C[i][j]表示i点到j点正好经过K条边的路径数。而floyd则是每次使用一个中间点k去更新i,j之间的距离,那么更新成功表示i,j之间恰有一个点k时的最短路,如果做N次floyd那么不就是i,j之间借助N个点时的最短路了?考虑当a[i][k]+a[k][j]<c[i][j]的时 候,c[i][j]=a[i][k]+a[k][j],这样c[i][j]保存了i,j之间有一个点的最短路,第二次将c[i][j]拷贝回到a[i] [j]当中,并将c[i][j]重新置为INF,再做一次,则是在原来的基础上在i,j之间再用一个点k来松弛,这时候i,j之间实际上已经是两个点了, 之后重复这么做就好了,可以利用二进制加速
好神的……用的是类似矩阵乘法快速幂的思想?以及floyd的性质= =
我掉过的坑:保存当前路径长度的dis数组要有dis[i][i]=0,但保存图的map数组不可以初始化为map[i][i]=0,因为没有这条边……如果加了,倍增乘完以后就不对了= =,走两步走过的距离可能会变成原地不动+走一步,这是不科学的……
/**************************************************************
Problem: 1706
User: Tunix
Language: C++
Result: Accepted
Time:192 ms
Memory:2152 kb
****************************************************************/ //BZOJ 1706
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
inline int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=,INF=~0u>>;
typedef long long LL;
/******************tamplate*********************/
int n,m,s,t,cnt,x[N],y[N],len[N],c[N];
struct Matrix{
int v[N][N];
int* operator [] (int x) {return v[x];}
Matrix(int x=){memset(v,x,sizeof v);}
}map(0x3f),dis(0x3f),ans(0x3f),tmp(0x3f); void floyd(Matrix &a,Matrix &b,Matrix &c){
F(k,,cnt) F(i,,cnt) F(j,,cnt)
if (c[i][j]>a[i][k]+b[k][j])
c[i][j]=a[i][k]+b[k][j];
}
void solve(int b){
F(i,,cnt) dis[i][i]=;
for(;b;b>>=){
if (b&){
ans=Matrix(0x3f);
floyd(map,dis,ans);
dis=ans;
}
floyd(map,map,tmp);
map=tmp;
tmp=Matrix(0x3f);
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1706.in","r",stdin);
freopen("1706.out","w",stdout);
#endif
n=getint(); m=getint(); s=getint(); t=getint();
F(i,,m){
len[i]=getint(); x[i]=getint(); y[i]=getint();
c[++cnt]=x[i]; c[++cnt]=y[i];
}
sort(c+,c+cnt+);
cnt=unique(c+,c+cnt+)-c-;
F(i,,m){
x[i]=lower_bound(c+,c+cnt+,x[i])-c;
y[i]=lower_bound(c+,c+cnt+,y[i])-c;
map[x[i]][y[i]]=map[y[i]][x[i]]=min(map[x[i]][y[i]],len[i]);
}
s=lower_bound(c+,c+cnt+,s)-c;
t=lower_bound(c+,c+cnt+,t)-c;
solve(n);
printf("%d\n",ans[s][t]);
return ;
}
1706: [usaco2007 Nov]relays 奶牛接力跑
Time Limit: 5 Sec Memory Limit: 64 MB
Submit: 383 Solved: 190
[Submit][Status][Discuss]
Description
FJ
的N(2 <= N <= 1,000,000)头奶牛选择了接力跑作为她们的日常锻炼项目。至于进行接力跑的地点
自然是在牧场中现有的T(2 <= T <= 100)条跑道上。 农场上的跑道有一些交汇点,每条跑道都连结了两个不同的交汇点
I1_i和I2_i(1 <= I1_i <= 1,000; 1 <= I2_i <=
1,000)。每个交汇点都是至少两条跑道的端点。 奶牛们知道每条跑道的长度length_i(1 <= length_i <=
1,000),以及每条跑道连结的交汇点的编号 并且,没有哪两个交汇点由两条不同的跑道直接相连。你可以认为这些交汇点和跑道构成了一张图。
为了完成一场接力跑,所有N头奶牛在跑步开始之前都要站在某个交汇点上(有些交汇点上可能站着不只1头奶牛)。当然,她们的站位要保证她们能够将接力棒顺
次传递,并且最后持棒的奶牛要停在预设的终点。
你的任务是,写一个程序,计算在接力跑的起点(S)和终点(E)确定的情况下,奶牛们跑步路径可能的最小总长度。显然,这条路径必须恰好经过N条跑道。
Input
* 第1行: 4个用空格隔开的整数:N,T,S,以及E
* 第2..T+1行: 第i+1为3个以空格隔开的整数:length_i,I1_i,以及I2_i, 描述了第i条跑道。
Output
* 第1行: 输出1个正整数,表示起点为S、终点为E,并且恰好经过N条跑道的路 径的最小长度
Sample Input
11 4 6
4 4 8
8 4 9
6 6 8
2 6 9
3 8 9
Sample Output
HINT
Source
【BZOJ】【1046】/【POJ】【3613】【USACO 2007 Nov】Cow Relays 奶牛接力跑的更多相关文章
- BZOJ 1641 USACO 2007 Nov. Cow Hurdles 奶牛跨栏
[题解] 弗洛伊德.更新距离的时候把$f[i][j]=min(f[i][j],f[i][k]+f[k][j])$改为$f[i][j]=min(f[i][j],max(f[i][k],f[k][j])) ...
- BZOJ_[usaco2007 Nov]relays 奶牛接力跑_离散化+倍增弗洛伊德
BZOJ_[usaco2007 Nov]relays 奶牛接力跑_离散化+倍增弗洛伊德 Description FJ的N(2 <= N <= 1,000,000)头奶牛选择了接力跑作为她们 ...
- 【BZOJ1706】[usaco2007 Nov]relays 奶牛接力跑 矩阵乘法
[BZOJ1706][usaco2007 Nov]relays 奶牛接力跑 Description FJ的N(2 <= N <= 1,000,000)头奶牛选择了接力跑作为她们的日常锻炼项 ...
- BZOJ 1706: [usaco2007 Nov]relays 奶牛接力跑
Description FJ的N(2 <= N <= 1,000,000)头奶牛选择了接力跑作为她们的日常锻炼项目.至于进行接力跑的地点 自然是在牧场中现有的T(2 <= T < ...
- 【BZOJ】1706: [usaco2007 Nov]relays 奶牛接力跑
[题意]给定m条边的无向图,起点s,终点t,要求找出s到t恰好经过n条边的最短路径.n<=10^6,m<=100. [算法]floyd+矩阵快速幂 [题解] 先对点离散化,得到点数N. 对 ...
- bzoj 1706: [usaco2007 Nov]relays 奶牛接力跑——倍增floyd
Description FJ的N(2 <= N <= 1,000,000)头奶牛选择了接力跑作为她们的日常锻炼项目.至于进行接力跑的地点 自然是在牧场中现有的T(2 <= T < ...
- bzoj 1706: [usaco2007 Nov]relays 奶牛接力跑【矩阵乘法+Floyd】
唔不知道怎么说--大概核心是把矩阵快速幂的乘法部分变成了Floyd一样的东西,非常之神 首先把点离散一下,最多有200个,然后建立邻接矩阵,a[u][v]为(u,v)之间的距离,没路就是inf 然后注 ...
- BZOJ 1706: [usaco2007 Nov]relays 奶牛接力跑 倍增Floyd
题不难,但是一开始把读入看错了,调了半天qaq~ Code: #include <bits/stdc++.h> #define N 300 #define setIO(s) freopen ...
- [bzoj1706] [usaco2007 Nov]relays 奶牛接力跑
大概是叫倍增Floyd? 显然最多200个点...f[i][j][k]表示从j到k,走2^i步的最小路程.就随便转移了.. 查询的话就是把n二进制位上是1的那些都并起来. #include<cs ...
随机推荐
- 关于SQL表联接
以SQL2008为例,Microsoft SQL Server 2008支持四种表运算符-JOIN,APPLY,PIVOT,UNPIVOT.JOIN表运算符是ANSI标准,而其他三种是T-SQL对标准 ...
- C# .Net三层架构[转]
C# .Net三层架构[转] 编写人:CC阿爸 2014-3-14 希望朋友们留下自己对三层架构的理解... 三层体系结构的概念 用户界面表示层(USL) 业务逻辑层(BLL) 数据访问层(D ...
- 关键字替换排除HTML标签属性字符
解决办法: 1.打开文件e/class/functions.php 2.找到函数 ReplaceKey($newstext,$classid=0) 3.找到替换代码 if(STR_IREPLACE) ...
- Delphi XE5 for android 调用Java类库必看的文件
C:\Program Files\Embarcadero\RAD Studio\12.0\source\rtl\android 的目录 Androidapi.AppGlue.pasAndroidapi ...
- Jquery在项目中的总结
1.构造对象 var _getSearchArg = function () { var argModel = {}; argModel.Txt = value; argModel.Code = va ...
- ASP.NET中前台调用后台的方法
学习文章:http://www.cnblogs.com/kingteach/archive/2010/11/12/1875633.html 练习代码: 前台: <html xmlns=" ...
- 十天学会单片机Day3 D/A与A/D转换器
D/A转换器 1.二进制权电阻网络型D/A转换器 基准电压Vref 数据D(d3d2d1d0) 输出模拟电压V0 i0 = Vref/8R i1 = Vref/4R i2 = Vref/ ...
- programming ruby
ri #rdoc reader attr_reader attr_writer @@xx 类变量都是私有的 def 类名.xx end 类方法 [1,3,5,7].inject(0){|sum,e| ...
- webpack 学习笔记 02 快速入门
webpack 的目标 将依赖项分块,按需加载. 减少web app的初始加载时间. 使每一个静态集合都能够作为组件使用. 有能力集成第三方库,作为组件使用. 高度可配置化. 适用于大型项目. INS ...
- 对云风 cstring 第二次解析
前言 从明天起 关心粮食和蔬菜 我有一所房子 面朝大海 春暖花开 本文前提条件 1.了解 posix 线程 2.了解 原子操作 3.具备简单C基础,或者 你也敲一遍. 如果上面不太清楚,你可以翻看我以 ...