Cow Relays POJ - 3613 邻接矩阵的简单用法

19 篇文章 0 订阅
19 篇文章 0 订阅

本题的大意就是问从S 到 T 经过边得个数恰为k的最短路是多少。

如果学过离散数学 就应该知道 邻接矩阵A
A^1里的元素a[i][j] 代表i到j的走一步一条路;
A^2里的元素a[i][j] 代表i到j的走两步一条路 ;
A^n里的元素a[i][j] 代表i到j的走N步一条路 ;
然后再矩阵快速幂一下就好

代码如下

/*
 * Author       :  Echo
 * Email        :  1666424499@qq.com  
 * Description  :   
 * Created Time :  2017/10/6 18:08:21
 * Last Modify  :  2017/10/6 19:02:49
 * File Name    :  a.cpp
 */
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <time.h>
#define LL long long
#define mem(a,k) memset(a,k,sizeof(a))
#include <map>
using namespace std;
const int maxint = -1u>>1;
const int maxn=2e2+100;
const int maxm=1e4+100;
int cnt=0;
struct node{
    int an[maxn][maxn];
    void set(){
        for(int i=1;i<=200;i++)
            for(int j=1;j<=200;j++)
                an[i][j]=1e9;
    }
    void copy(node a){
        for(int i=1;i<=cnt;i++)
            for(int j=1;j<=cnt;j++)
                an[i][j]=a.an[i][j];
    }
    node cal(node a,node b){
        node res;
        res.set();
        for(int i=1;i<=cnt;i++)
            for(int k=1;k<=cnt;k++)
                for(int j=1;j<=cnt;j++)
                    if(res.an[i][j]>a.an[i][k]+b.an[k][j])
                       res.an[i][j]=a.an[i][k]+b.an[k][j];
        return res;
    }
}road,ans;
void QSM(int n){
    ans.copy(road);
    n--;
    while(n){
        if(n%2==1){
            ans=ans.cal(ans,road);
        }
        road=road.cal(road,road);
        n>>=1;
    }
}
int main(){
    int n,m,s,t;
    cin>>n>>m>>s>>t;
    map<int,int >mp;
    road.set();
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>c>>a>>b;
        if(mp[a]==0)mp[a]=++cnt;
        if(mp[b]==0)mp[b]=++cnt;
        //printf("%d:%d;%d:%d %d\n",a,mp[a],b,mp[b],road.an[mp[a]][mp[b]]);
        if(road.an[mp[a]][mp[b]]>c){
            road.an[mp[a]][mp[b]]=c;
            road.an[mp[b]][mp[a]]=c;
        }
    }
    QSM(n);
    //printf("%d %d\n",mp[s],mp[t]);
    printf("%d\n",ans.an[mp[s]][mp[t]]);
    return 0;
}
/*


2 6 6 4
11 4 6
4 4 8
8 4 9
6 6 8
2 6 9
3 8 9

10 

 */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值