- /*
- 从这抄来的,自己不会写,-_-! http://hi.baidu.com/lxxstar1226/item/9119a40de25c55faa1103462
- 用到了矩阵相关知识,见转自Matrix67的博客:http://blog.sina.com.cn/s/blog_680c5cd50100khvp.html
- */
- #include <cstdio>
- #include <iostream>
- #include <cstring>
- #define mem(a,x) memset(a,x,sizeof(a))
- using namespace std;
- const int NN=205;
- const int MM=1005;
- const int INF=1000000001;
- int n,m,S,T,vcnt;
- int hash[MM],dis[NN][NN],tmp[NN][NN],f[NN][NN];
- void solve(int n) //求f[i][j],f[i][j]为从节点i到节点j的步数为n的最短路,二分n,类似于快速幂过程
- {
- int i,j,k;
- while(n)
- {
- 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步。
- {
- for(i=1; i<=vcnt; i++)
- for(j=1; j<=vcnt; j++)
- tmp[i][j]=INF;
- for(k=1; k<=vcnt; k++) //n=1110 11
- for(i=1; i<=vcnt; i++)
- for(j=1; j<=vcnt; j++) //我擦!写成j<vcnt,WA两次
- if(tmp[i][j]>f[i][k]+dis[k][j])
- tmp[i][j]=f[i][k]+dis[k][j];
- for(i=1; i<=vcnt; i++)
- for(j=1; j<=vcnt; j++)
- f[i][j]=tmp[i][j]; //最后一次n=1,一定会进行这一步
- }
- for(i=1; i<=vcnt; i++)
- for(j=1; j<=vcnt; j++)
- tmp[i][j]=INF;
- for(k=1; k<=vcnt; k++)
- for(i=1; i<=vcnt; i++)
- for(j=1; j<=vcnt; j++)
- if(tmp[i][j]>dis[i][k]+dis[k][j])
- tmp[i][j]=dis[i][k]+dis[k][j]; //n步=n/2步+n/2步
- for(i=1; i<=vcnt; i++)
- for(j=1; j<=vcnt; j++)
- dis[i][j]=tmp[i][j];
- n=n/2;
- }
- return ;
- }
- int main()
- {
- vcnt=0;
- mem(hash,0);
- for (int i=0; i<NN; i++)
- {
- for (int j=0; j<NN; j++)
- f[i][j]=dis[i][j]=INF;
- f[i][i]=0;
- }
- scanf("%d%d%d%d",&n,&m,&S,&T);
- int u,v,w;
- for (int i=1; i<=m; i++)
- {
- scanf("%d%d%d",&w,&u,&v);
- if (!hash[u]) hash[u]=++vcnt;
- if (!hash[v]) hash[v]=++vcnt;
- dis[hash[u]][hash[v]]=w;
- dis[hash[v]][hash[u]]=w;
- }
- solve(n);
- printf("%d\n",f[hash[S]][hash[T]]);
- return 0;
- }
恰好K步最短路
最新推荐文章于 2024-10-07 18:15:04 发布