POJ 3613 Cow Relays Floyd+快速幂加速
来源:互联网 发布:configparser python 编辑:程序博客网 时间:2024/06/05 11:24
题目大意:求从S到T 恰好经过k条边的最短路。(2<=k<=1000000)
解题思路:最开始看到题目以为是K短路,不过看到K的数量级就明显不适合了。
根据题意,既有最短路,k这么大,时间限制还是1s,便想到去优化。
然后看到点数为1000,而边数最多只有100,先进行一步离散化,不过复杂度还是不够,然后就开始考虑这道题的特殊性了。
K最多为1000,000,而边数只有一百,可以预见中间有许多状态是重复出现的,甚至有可能在一个环中不停地走。
于是考虑把中间重复的计算给优化一下。便想到了快速幂优化和ST算法。(这两个都是能基于重复的状态进行优化)
而便于重复状态的记录的话,用矩阵来存储状态是再合适不过的了,由此想到最短路用Floyd来求。
先简述一下快速幂优化的思想:
如果想求K^a, 假设a=43. 我们把a转化为二进制便是 101011
接下来表示时我们把指数都用二进制表示,原式便是求 K^(101011) ,
=K^(1<<0) + K^(1<<1) + K^(1<<3) +K^(1<<5) ,
而K^(1<<1)= (K^(1<<0))^2 , K^(1<<2)= (K^(1<<1))^2 , K^(1<<3)= (K^(1<<2))^2 ,K^(1<<4)= (K^(1<<3))^2 ,K^(1<<5)= (K^(1<<4))^2 ....
也就是说每一位都可以由上一位的平方得到,原来的指数级运算便成了加法运算..
而只要是1e9级以内的指数运算我们都可以在32次运算内完成....( 很强大... ) ( 当然...不要给我说数据溢出什么的...那种题一般要取余,取余方法自己找快速幂看 )
再回到这题,用Floyd算法的话,
假设从a到b经过恰好经过 (1<<i) 条路的最短路是len[a][b][ 1<<i ]=min(len[ a ][ c ][ 1<<(i-1) ] + len(len[ c ][ b ][ 1<<(i-1) ]
哪怕是经过101011条路径的最短路我们也都可以像上面的优化一样依次求出。
具体实现看代码
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define FOR(i,l,r) for(int i=(l);i<=(r);++i)#define REP(i,n) for(int i=0;i<(n);++i)#define N 1010#define INF 1e9#define min(a,b) (a<b?a:b)int map[2][N][N];int ans[2][N][N];int f[N];bool flag[N];void floyd(int num,int cur,int pre){ REP(i,num) REP(j,num) map[cur][f[i]][f[j]]=INF; REP(k,num) REP(i,num) REP(j,num) map[cur][f[i]][f[j]]=min(map[cur][f[i]][f[j]],map[pre][f[i]][f[k]]+map[pre][f[k]][f[j]]);}int main(){ int n,m,start,end; int u,v,c; while(cin>>n>>m>>start>>end) { memset(flag,0,sizeof(flag)); FOR(i,1,1000) FOR(j,1,1000) map[0][i][j]=INF; //初始化 int num=0; while(m--) { scanf("%d%d%d",&c,&u,&v); map[0][u][v]=map[0][v][u]=c; if(!flag[u]) f[num++]=u,flag[u]=1; //离散化 if(!flag[v]) f[num++]=v,flag[v]=1; //离散化 } REP(i,num) { REP(j,num) ans[0][f[i]][f[j]]=INF; ans[0][f[i]][f[i]]=0; //初始化 } int cur=0,pre=1; int temp1=0,temp2=1; //temp1是当前状态,temp2是之前的状态 //因为map[1<<i][a][b] 只与 map[1<<(i-1)][x][y] 有关 //所以这两个数组能循环利用 //没必要开32位,开两位足以,是一种空间上的优化 while(n) { temp1^=1,temp2^=1; floyd(num,temp1,temp2);//i从0开始,在进行第i次while()循环时,求出从a到b恰好经过(1<<i)条边的最短路是多少 if(n&1) //如果当前位为1才进行计算,把ans进行更新 { cur^=1,pre^=1;//和temp1,temp2的效果是一样的 REP(i,num) REP(j,num) ans[cur][f[i]][f[j]]=INF;//只用对离散化后的点初始化 REP(k,num) REP(i,num) REP(j,num) ans[cur][f[i]][f[j]]=min(ans[cur][f[i]][f[j]],ans[pre][f[i]][f[k]]+map[temp2][f[k]][f[j]]); //在离散化后的点中进行Floyd } n>>=1; } cout<<ans[cur][start][end]<<endl; } return 0;}
- POJ 3613 Cow Relays Floyd+快速幂加速
- POJ 3613 Cow Relays floyd + 快速幂
- POJ 3613 Cow Relays floyd+快速幂
- poj 3613 Cow Relays (floyd快速幂)
- Poj 3613 Cow Relays【Floyd+快速幂】
- POJ 3613 Cow Relays (floyd + 矩阵快速幂)
- POJ题目3613 Cow Relays(Floyd+快速幂)
- POJ 3613 Cow Relays(矩阵模板+快速幂+floyd)
- poj 3613 Cow Relays (K步最短路+Floyd+矩阵快速幂)
- poj 3613 Cow Relays (floyd+矩阵快速幂+坐标离散化)
- POJ 3613 Cow Relays (Floyd + 矩阵快速幂 + 离散化 神题!)
- POJ 3613 Cow Relays k步最短路 (floyd + 矩阵快速幂)
- 【Floyd求最短路+快速幂】PKU-3613-Cow Relays
- POJ--3613[Cow Relays] floyd 倍增法
- POJ--3613[Cow Relays] floyd 倍增法
- POJ 3613 Cow Relays Floyd最短路
- POJ 3613 Cow Relays 倍增Floyd
- POJ 3613 Cow Relays floyd+矩阵
- 八大排序算法:简单插入排序、冒泡排序、希尔排序、快速排序、堆排序、归并排序等总结。
- 代码的抽象三原则
- 23种设计模式(11):责任连模式
- Codeforces Beta Round #93 (Div. 2 Only) A题
- @高三--我的一些语录,一些心情。上课无聊,写在草稿本上的
- POJ 3613 Cow Relays Floyd+快速幂加速
- sqoop错误解决
- 有关使用xsl输出csv格式文档的实践小结
- 跨平台调试,安卓真机无法显示个别图片的问题(一)
- 回调函数和函数指针
- VC++中用内存映射文件
- Flex 弹出窗派发事件主页面用于接收
- S5PV210的16bit硬件ECC校验
- Webkit内核探究