灵魂滚烫|

fhq_treap

园龄:5年6个月粉丝:66关注:21

[USACO07NOV]Cow Relays G

题目大意

给出一张无向连通图(点数小于1000),求S到E经过k条边的最短路。

算法

这是之前国庆模拟赛的题
因为懒 所以就只挑一些题写博客
在考场上写了个dp 然后水到了50分 出考场和神仙们一问才知道是lyd蓝书原题

我们考虑有两个floyd的矩阵 A代表走了x条边的矩阵 B代表走了y条边的矩阵
那么我们想求出C这个代表走了(x + y)这个矩阵的值呢
我们考虑这么一个式子
C[i][j]=min(A[i][k]+B[k][j])
然后我们发现 其中A[i][k]+B[k][j]这个式子和矩阵乘的式子很像
我们把矩阵乘的 + 改成 min 即可
那么我们可以考虑将初始给定A矩阵(也就是走了一次的floyd矩阵)进行n - 1次转移
An[i][j]=(A[i][j])n1
然后用快速幂就可以实现了

代码

#include <bits/stdc++.h>
using namespace std;
int num[1000005];
int n,s,t,e,tol;
struct map
{
    int a[500][500];
    map operator * (const map &x) const //重载运算符,一会儿要用
    {
        map c;
        memset(c.a,0x3f3f3f3f,sizeof(c.a));//取min,显然置大数
        for(int k=1;k<=tol;k++)
            for(int i=1;i<=tol;i++)
                for(int j=1;j<=tol;j++)
                    c.a[i][j]=min(c.a[i][j],a[i][k]+x.a[k][j]);
        return c;		
    }
}dis,ans;
void init()
{
    memset(dis.a,0x3f3f3f3f,sizeof(dis.a));
    int x,y,z;
    cin>>n>>t>>s>>e;
    for(int i=1;i<=t;i++)
    {
        scanf("%d %d %d",&x,&y,&z);
        if(!num[y])  //这里做一个离散化
            num[y]=++tol;
        if(!num[z])
            num[z]=++tol;
        dis.a[num[y]][num[z]]=dis.a[num[z]][num[y]]=x;
    }
}
void doit() //快速幂
{
    n--;
    ans=dis;
    while(n)
    {
        if(n&1)
            ans=ans*dis;
        dis=dis*dis;
        n>>=1;
    }
}
int main()
{
    init();
    doit();
    cout<<ans.a[num[s]][num[e]];
}

本文作者:fhq_treap

本文链接:https://www.cnblogs.com/dixiao/p/13804947.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   fhq_treap  阅读(125)  评论(0编辑  收藏  举报
编辑推荐:
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
阅读排行:
· 用 DeepSeek 给对象做个网站,她一定感动坏了
· DeepSeek+PageAssist实现本地大模型联网
· 手把手教你更优雅的享受 DeepSeek
· 腾讯元宝接入 DeepSeek R1 模型,支持深度思考 + 联网搜索,好用不卡机!
· 从 14 秒到 1 秒:MySQL DDL 性能优化实战
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起