题目描述
N(1≤N≤1000)头牛要去参加在某农场举行的一场编号为x(1≤x≤N)的牛的派对。有M(1≤M≤100000)条有向道路,每条道路长Ti(1≤Ti≤100);每头牛参加派对后都必须回到家,每头牛都会选择最短路。求这N头牛的最短路(一个来回)中最长的一条的长度。
特别提醒:可能有权值不同的重边。
输入输出格式
输入格式:
第一行,3个空格分开的整数N,M,X。
第二行至第M+1行:3个用空格分开的整数Ai,Bi,Ti,表示有一条从Ai到Bi的路长度为Ti。
输出格式:
一行:最长的最短路长度。
输入输出样例
输入样例:
4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3
输出样例:
10
分析
一道最短路径的题目
我的方法是用 spfa 算法,再进行一些简单优化
spfa算法
算法分析
1.用dis数组记录点到有向图的任意一点距离,初始化起点距离为0,其余点均为INF,起点入队。
2.判断该点是否存在。(未存在就入队,标记)
3.队首出队,并将该点标记为没有访问过,方便下次入队。
4.遍历以对首为起点的有向边(t,i),如果dis[i]>dis[t]+w(t,i),则更新dis[i]。
5.如果i不在队列中,则入队标记,一直到循环为空。
例题
想练习 spfa 算法的可以去 洛谷 上练练手
详细请看 spfa
我还用了一种容器----deque(双端队列)
双端队列deque
简介
deque,即双端队列(double ended queue),是一种可以在两端扩展或收缩的序列化容器。
deque 是C++ 标准模板库的一部分,想要使用 deque,需要在程序中包含头文件 deque 。
#include<deque>
迭代器
deque.begin():指向deque首个元素。
deque.end():指向deque尾元素的下一个位置。
deque.rbegin():指向deque尾元素的反向迭代器,即rbegin()指向尾元素,rbegin-1指向倒数第二个元素。
deque.rend():指向deque头元素前一个位置的反向迭代器,即rend()指向头元素前一个位置元素,rbegin-1指向第一个元素
deque.cbegin():指向deque首元素,与begin()相同。增加了const属性,不能用于修改元素。
deque.cend():指向deque尾元素下一个位置,与end()相同。增加了const属性,不能用于修改元素。
deque.crbegin():指向deque尾元素的反向迭代器,与rbegin()相同。增加了const属性,不能用于修改元素。
deque.crend():指向deque头元素前一个位置的反向迭代器,与rend()相同。增加了const属性,不能用于修改元素。
用法(函数)
- size()——元素个数
- max_size()——最多能容纳元素个数
- resize(n)——改变deque大小为n
- empty()——判断deque是否为空
- shrink_to_fit()——要求deque减小容量已适应元素个数
- at()——访问deque元素
- front()和back()——访问deque头尾元素
- assign()——指定deque元素
- push_back()——添加元素(deque尾部)
- push_front()——添加元素(deque头部)
- pop_back()——移除deque元素(尾部)
- pop_front()——删除deque元素(头部)
- insert()——添加元素(任意位置)
- erase()——删除元素(任意位置)
- clear()——清空元素
- swap()——交换元素
- emplace()——插入元素
- emplace_back()——在deque尾部插入元素
- emplace_front()——在deque尾部插入元素
***详细请看这里 双端队列deque ***
废话不多说,我们来看一看代码
Code
注意 :int 不能改为 long long 已经试过会出错,以为0x3f3f3f3f是 int 的最大值, long long 的最大值是 0x7fffffff ,但是用 0x7fffffff 会报错(我也不知道为什么),知道原因的请在评论区支指出,谢谢~
本代码AC速度 14 毫秒 ,速度超快
#include<iostream>
#include<cstdio>
#include<deque>
#include<cstring>
using namespace std;
int n,m,x,a,b,t,i,j,f[1100][1100],d[1100],vis[1100],dd[1100],sum=0,ans=0;
int main()
{
memset(vis,0,sizeof(vis));
memset(d,0x3f3f3f3f,sizeof(d));
scanf("%d%d%d",&n,&m,&x);
for(i=1;i<=1000;i++)
for(j=1;j<=1000;j++)
f[i][j]=0x3f3f3f3f;
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&t);
f[a][b]=min(f[a][b],t);
}
d[x]=0;
deque<int>q;
q.push_front(x);
while(!q.empty())
{
t=q.front();
q.pop_front();
if((q.size()+1)*d[t]>sum)
{
q.push_back(t);
continue;
}
sum-=d[t];
vis[t]=0;
for(i=1;i<=n;i++)
{
if(f[t][i]!=0x3f3f3f3f&&d[i]>d[t]+f[t][i])
{
d[i]=d[t]+f[t][i];
if(!vis[i])
{
vis[i]=1;
sum+=d[i];
if(q.empty()||d[i]>d[q.front()])
q.push_back(i);
else
q.push_front(i);
}
}
}
}
q.clear();
memset(dd,0x3f3f3f3f,sizeof(dd));
memset(vis,0,sizeof(vis));
dd[x]=0;
q.push_front(x);
sum=0;
while(!q.empty())
{
t=q.front();
q.pop_front();
if(q.size()*d[t]>sum)
q.push_back(t);
sum-=dd[t];
vis[t]=0;
for(i=1;i<=n;i++)
{
if(f[i][t]!=0x3f3f3f3f&&dd[i]>dd[t]+f[i][t])
{
dd[i]=dd[t]+f[i][t];
if(!vis[i])
{
vis[i]=1;
sum+=dd[i];
if(q.empty()||dd[i]>d[q.front()])
q.push_back(i);
else
q.push_front(i);
}
}
}
}
for(i=1;i<=n;i++)
if(d[i]!=0x3f3f3f3f&&dd[i]!=0x3f3f3f3f)
ans=max(ans,d[i]+dd[i]);
printf("%d",ans);
return 0;
}
//spfa