恰好K步最短路

本文介绍了解决POJ3613恰好K步最短路问题的一种方法,利用矩阵乘法和二分思想进行高效计算。适用于竞赛编程中的图论题目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

POJ3613-恰好K步最短路

分类: ACM 图论   787人阅读  评论(0)  收藏  举报
[cpp]  view plain copy
  1. /* 
  2. 从这抄来的,自己不会写,-_-!  http://hi.baidu.com/lxxstar1226/item/9119a40de25c55faa1103462 
  3. 用到了矩阵相关知识,见转自Matrix67的博客:http://blog.sina.com.cn/s/blog_680c5cd50100khvp.html 
  4. */  
  5. #include <cstdio>  
  6. #include <iostream>  
  7. #include <cstring>  
  8. #define mem(a,x) memset(a,x,sizeof(a))  
  9. using namespace std;  
  10.   
  11. const int NN=205;  
  12. const int MM=1005;  
  13. const int INF=1000000001;  
  14.   
  15. int n,m,S,T,vcnt;  
  16. int hash[MM],dis[NN][NN],tmp[NN][NN],f[NN][NN];  
  17.   
  18. void solve(int n)  //求f[i][j],f[i][j]为从节点i到节点j的步数为n的最短路,二分n,类似于快速幂过程  
  19. {  
  20.     int i,j,k;  
  21.     while(n)  
  22.     {  
  23.         if(n%2)  //n为奇数时,n步=n/2步+n/2步+1步,这里是在补充多的一步,这一步也不是单纯的一步。。。是多出来的整个部分,如n=11时,n=(4+4)+3,多出来的部分是3步,这是因为n要拆成2^a+2^a+b,这里补上b步,后面计算2*2^a步。  
  24.         {  
  25.             for(i=1; i<=vcnt; i++)  
  26.                 for(j=1; j<=vcnt; j++)  
  27.                     tmp[i][j]=INF;  
  28.   
  29.             for(k=1; k<=vcnt; k++)    //n=1110  11  
  30.                 for(i=1; i<=vcnt; i++)  
  31.                     for(j=1; j<=vcnt; j++)  //我擦!写成j<vcnt,WA两次  
  32.                         if(tmp[i][j]>f[i][k]+dis[k][j])  
  33.                             tmp[i][j]=f[i][k]+dis[k][j];  
  34.   
  35.             for(i=1; i<=vcnt; i++)  
  36.                 for(j=1; j<=vcnt; j++)  
  37.                     f[i][j]=tmp[i][j]; //最后一次n=1,一定会进行这一步  
  38.         }  
  39.         for(i=1; i<=vcnt; i++)  
  40.             for(j=1; j<=vcnt; j++)  
  41.                 tmp[i][j]=INF;  
  42.         for(k=1; k<=vcnt; k++)  
  43.             for(i=1; i<=vcnt; i++)  
  44.                 for(j=1; j<=vcnt; j++)  
  45.                     if(tmp[i][j]>dis[i][k]+dis[k][j])  
  46.                         tmp[i][j]=dis[i][k]+dis[k][j];  //n步=n/2步+n/2步  
  47.         for(i=1; i<=vcnt; i++)  
  48.             for(j=1; j<=vcnt; j++)  
  49.                 dis[i][j]=tmp[i][j];  
  50.         n=n/2;  
  51.     }  
  52.     return ;  
  53. }  
  54.   
  55. int main()  
  56. {  
  57.     vcnt=0;  
  58.     mem(hash,0);  
  59.     for (int i=0; i<NN; i++)  
  60.     {  
  61.         for (int j=0; j<NN; j++)  
  62.             f[i][j]=dis[i][j]=INF;  
  63.         f[i][i]=0;  
  64.     }  
  65.     scanf("%d%d%d%d",&n,&m,&S,&T);  
  66.     int u,v,w;  
  67.     for (int i=1; i<=m; i++)  
  68.     {  
  69.         scanf("%d%d%d",&w,&u,&v);  
  70.         if (!hash[u]) hash[u]=++vcnt;  
  71.         if (!hash[v]) hash[v]=++vcnt;  
  72.         dis[hash[u]][hash[v]]=w;  
  73.         dis[hash[v]][hash[u]]=w;  
  74.     }  
  75.     solve(n);  
  76.     printf("%d\n",f[hash[S]][hash[T]]);  
  77.     return 0;  
  78. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值