bzoj1726【Usaco2006 Nov】Roadblocks第二短路
2015-10-19 23:53
381 查看
1726: [Usaco2006 Nov]Roadblocks第二短路
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 907 Solved: 441
[Submit][Status][Discuss]
Description
贝茜把家搬到了一个小农场,但她常常回到FJ的农场去拜访她的朋友。贝茜很喜欢路边的风景,不想那么快地结束她的旅途,于是她每次回农场,都会选择第二短的路径,而不象我们所习惯的那样,选择最短路。 贝茜所在的乡村有R(1<=R<=100,000)条双向道路,每条路都联结了所有的N(1<=N<=5000)个农场中的某两个。贝茜居住在农场1,她的朋友们居住在农场N(即贝茜每次旅行的目的地)。贝茜选择的第二短的路径中,可以包含任何一条在最短路中出现的道路,并且,一条路可以重复走多次。当然咯,第二短路的长度必须严格大于最短路(可能有多条)的长度,但它的长度必须不大于所有除最短路外的路径的长度。
Input
* 第1行: 两个整数,N和R,用空格隔开* 第2..R+1行: 每行包含三个用空格隔开的整数A、B和D,表示存在一条长度为 D(1 <= D <= 5000)的路连接农场A和农场B
Output
* 第1行: 输出一个整数,即从农场1到农场N的第二短路的长度Sample Input
4 41 2 100
2 4 200
2 3 250
3 4 100
Sample Output
450输出说明:
最短路:1 -> 2 -> 4 (长度为100+200=300)
第二短路:1 -> 2 -> 3 -> 4 (长度为100+250+100=450)
HINT
Source
Gold以1和n分别为起点跑spfa,将每个点最短路径记作d[i][0]和d[i][1]。再枚举每一条边,用d[i][0]+d[e[j].to]+e[j].w更新答案。注意这里的次短路是严格大于最短路。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define MAXN 200050
#define INF 1000000000
using namespace std;
struct edge_type
{
int next,to,w;
}e[MAXN];
int n,m,a,b,x,cnt=0,d[5005][2],ans=INF,head[5005],tmp;
bool inq[5005];
queue<int> q;
int read()
{
int x=0;
char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x;
}
void add_edge(int u,int v,int w)
{
e[++cnt].to=v;
e[cnt].w=w;
e[cnt].next=head[u];
head[u]=cnt;
}
void spfa(int s,int p)
{
memset(inq,false,sizeof(inq));
d[s][p]=0;
q.push(s);
inq[s]=true;
while (!q.empty())
{
int y=q.front();
inq[y]=false;
q.pop();
for(int i=head[y];i;i=e[i].next) if (d[e[i].to][p]>d[y][p]+e[i].w)
{
d[e[i].to][p]=d[y][p]+e[i].w;
if (!inq[e[i].to])
{
q.push(e[i].to);
inq[e[i].to]=true;
}
}
}
}
int main()
{
memset(d,0x7f,sizeof(d));
memset(head,0,sizeof(head));
n=read(); m=read();
F(i,1,m)
{
a=read(); b=read(); x=read();
add_edge(a,b,x);
add_edge(b,a,x);
}
spfa(1,0);
spfa(n,1);
F(i,1,n) for(int j=head[i];j;j=e[j].next)
{
tmp=d[i][0]+d[e[j].to][1]+e[j].w;
if (tmp>d
[0]&&tmp<ans) ans=tmp;
}
printf("%d\n",ans);
}
相关文章推荐
- [LeetCode] Find Median from Data Stream
- 泛型的内部原理:类型擦除以及类型擦除带来的问题
- getHibernateTemplate()
- stringstrream的使用及注意事项
- 加强学习
- CentOS编译安装LAMP
- C++中虚函数表的介绍
- SQL优化
- 团队项目-北航MOOC系统Android客户端 NABC
- Android安卓Fragment简单实现
- Spark修炼之道(高级篇)——Spark源码阅读:第三节 Spark Job的提交
- ReactiveCocoa,最受欢迎的iOS函数响应式编程库(2.5版),没有之一!
- iOS中定位功能的实现
- The import android.support.v4 cannot be resolved 问题解决方法
- ReactiveCocoa,最受欢迎的iOS函数响应式编程库(2.5版),没有之一!
- 爱码室Crawler & classification module项目工作分配
- C#实现 ffmpeg视频转码、播放
- 学习日志---linux 磁盘分区的挂载
- Fast floor/ceiling functions C
- UVa 1496 - Peach Blossom Spring