您的位置:首页 > 其它

BZOJ 1726 [Usaco2006 Nov]Roadblocks第二短路

2017-04-09 21:14 375 查看

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 4

1 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

挺好的一道图论题。
第一次窝以为和洛谷 玛利亚那道题差不多,结果拿了50分,就苟且地抄了题解。


解法一:

在spfa中更新,有三种情况,注意细节(似乎较容易出错)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int N=5005;
const int M=100005;
int n,m,cnt,dis1
,dis2
,hd
;
bool inq
;
queue<int>q;
struct edge
{
int to,nxt,val;
}v[2*M];
void addedge(int x,int y,int z)
{
++cnt;
v[cnt].to=y;
v[cnt].nxt=hd[x];
v[cnt].val=z;
hd[x]=cnt;
}
int main()
{
scanf("%d%d",&n,&m);
while(m--)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z),addedge(y,x,z);
}
memset(dis1,0x3f,sizeof(dis1));
memset(dis2,0x3f,sizeof(dis2));
dis1[1]=0;
inq[1]=1;
q.push(1);
while(!q.empty())
{
int u=q.front();
q.pop();
inq[u]=0;
for(int i=hd[u];i;i=v[i].nxt)
{
bool flg=0;
if(dis1[v[i].to]>dis1[u]+v[i].val)
{
dis2[v[i].to]=min(dis1[v[i].to],dis2[u]+v[i].val);
dis1[v[i].to]=dis1[u]+v[i].val;
flg=1;
}
else if(dis1[v[i].to]<dis1[u]+v[i].val&&dis2[v[i].to]>dis1[u]+v[i].val)
{
dis2[v[i].to]=dis1[u]+v[i].val;
flg=1;
}
else if(dis1[v[i].to]==dis1[u]+v[i].val&&dis2[v[i].to]>dis2[u]+v[i].val)
{
dis2[v[i].to]=dis2[u]+v[i].val;
flg=1;
}
if(flg&&!inq[v[i].to])
{
inq[v[i].to]=1;
q.push(v[i].to);
}
}
}
printf("%d\n",dis2
);
return 0;
}


解法二:

正反两次spfa,枚举中间的一条边(因为最多只可能有一条边与最短路不同),或一条边走了两次。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int N=5005;
const int M=100005;
const int inf=1e9+7;
int n,m,ans,mn,cnt=1,hd
,dis1
,dis2
;
bool inq
;
queue<int>q;
struct edge
{
int to,nxt,val;
}v[2*M];
void addedge(int x,int y,int z)
{
++cnt;
v[cnt].to=y;
v[cnt].nxt=hd[x];
v[cnt].val=z;
hd[x]=cnt;
}
void spfa(int s,int *dis)
{
memset(dis,0x3f,N*sizeof(int));
dis[s]=0;
inq[s]=1;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
inq[u]=0;
for(int i=hd[u];i;i=v[i].nxt)
if(dis[v[i].to]>dis[u]+v[i].val)
{
dis[v[i].to]=dis[u]+v[i].val;
if(!inq[v[i].to])
{
inq[v[i].to]=1;
q.push(v[i].to);
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
while(m--)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z),addedge(y,x,z);
}
spfa(1,dis1);
spfa(n,dis2);
ans=inf;
mn=dis1
;
for(int i=2;i<=cnt;i++)
{
int u=min(dis1[v[i].to]+dis2[v[i^1].to],dis1[v[i^1].to]+dis2[v[i].to])+v[i].val;
if(u!=mn&&u<ans)
ans=u;
}
for(int i=1;i<=n;i++)
for(int j=hd[i];j;j=v[j].nxt)
ans=min(ans,dis1[i]+dis2[i]+2*v[j].val);
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  图论