[USACO07NOV]Cow Relays G
2024-08-31 14:37:03
题目大意
给出一张无向连通图(点数小于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次转移
\(A_n[i][j] = (A[i][j]) ^ {n - 1}\)
然后用快速幂就可以实现了
代码
#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]];
}
最新文章
- QQ左侧滑动显示之自定义属性
- Mysql有没有语法可以在增加列前进行判断该列是否存在
- vim编辑器配置修改
- 【转】android如何浏览并选择图片 音频 视频
- 好的git教程
- PMBOK 项目管理 九大知识领域和五大流程
- HDU5086Revenge of Segment Tree(数论)
- Scala开发环境搭建与资源推荐
- 大数据阶乘(The factorial of large data)
- hadoop全分布式环境搭建
- 任务调度---crontab
- 玩转CSS3(二)---CSS3实现瀑布布局
- Python 中文(大写)数字转阿拉伯数字(转)
- Postman Could not get any response
- Java集合和泛型
- vb 三种启动模式
- sublime添加到鼠标右键打开文件的方法?
- QFileInfo
- ajax--底层代码
- poj1182 食物链(带权并查集)
热门文章
- 浅尝装饰器-@staticmethod 和@classmethod
- 全连接层dense作用
- Coursera Deep Learning笔记 序列模型(三)Sequence models &; Attention mechanism(序列模型和注意力机制)
- [火星补锅] siano 神奇的线段树
- 修炼Servlet
- Java并发:重入锁 ReentrantLock(一)
- linux shell脚本中的开头#!/bin/bash的含义
- linux exit 和 _exit的区别
- Python matplotlib pylab 画张图
- evaluate-reverse-polist-notation leetcode C++