P2865 [USACO06NOV]路障Roadblocks
Dijkstra-图论-最短路-次短路
题目大意
给出一个无向图,求出点 1 1 1到点 n n n的严格次短路
d i s [ ] dis[] dis[]数组存最短路, d i s t [ ] dist[] dist[]存次短路
更新的时候考虑多种情况
更新最短路时:之前的最短路就是当前的次短路
对于点
y
,
x
y,x
y,x(
y
,
x
y,x
y,x相邻)若
d
i
s
t
[
y
]
>
d
i
s
[
x
]
+
w
(
x
,
y
)
dist[y]>dis[x]+w(x,y)
dist[y]>dis[x]+w(x,y)且更新后的
d
i
s
t
[
y
]
dist[y]
dist[y]不等与最短路就更新
若满足
d
i
s
t
[
y
]
>
d
i
s
[
x
]
+
w
(
x
,
y
)
dist[y]>dis[x]+w(x,y)
dist[y]>dis[x]+w(x,y),更新
90 90 90分代码:
#include<cstdio>
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int Maxn=5010,inf=0x3f3f3f3f;
struct edge{
int v,len;
};
struct node{
int pos,dis;
bool operator <(const node &x)const
{
return x.dis<dis;
}
};
vector <edge> e[Maxn];
int dis[Maxn],dist[Maxn];
bool vis[Maxn];
int n,m;
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return s*w;
}
void dij()
{
priority_queue <node> q;
fill(dis+1,dis+1+n,inf);
fill(dist+1,dist+1+n,inf);
dis[1]=0,vis[1]=1,q.push(node{1,0});
while(!q.empty())
{
int x=q.top().pos;
q.pop();
for(int i=0;i<e[x].size();++i)
{
int y=e[x][i].v;
if(dis[y]>dis[x]+e[x][i].len)
{
dist[y]=dis[y];
dis[y]=dis[x]+e[x][i].len;
if(!vis[y])vis[y]=1,q.push(node{y,dis[y]});
}
else if(dist[y]>dis[x]+e[x][i].len && dis[x]+e[x][i].len!=dis[y])
{
dist[y]=dis[x]+e[x][i].len;
if(!vis[y])vis[y]=1,q.push(node{y,dis[y]});
}
if(dist[y]>dist[x]+e[x][i].len)
dist[y]=dist[x]+e[x][i].len;
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
n=read(),m=read();
for(int i=1;i<=m;++i)
{
int x=read(),y=read(),c=read();
e[x].push_back(edge{y,c});
e[y].push_back(edge{x,c});
}
dij();
printf("%d\n",dist[n]);
return 0;
}
下载数据一看,发现给出的图有重边(并且边权不同),而且正确次短路要经过该条边多次
去掉 v i s vis vis数组就AC了
#include<cstdio>
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int Maxn=5010,inf=0x3f3f3f3f;
struct edge{
int v,len;
};
struct node{
int pos,dis;
bool operator <(const node &x)const
{
return x.dis<dis;
}
};
vector <edge> e[Maxn];
int dis[Maxn],dist[Maxn];
bool vis[Maxn]; //我只去掉了vis数组的判断
int n,m;
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return s*w;
}
inline bool cmp(edge x,edge y)
{
return x.len<y.len;
}
void dij()
{
priority_queue <node> q;
fill(dis+1,dis+1+n,inf);
fill(dist+1,dist+1+n,inf);
dis[1]=0,vis[1]=1,q.push(node{1,0});
while(!q.empty())
{
int x=q.top().pos;
q.pop();
sort(e[x].begin(),e[x].end(),cmp);
for(int i=0;i<e[x].size();++i)
{
int y=e[x][i].v;
if(dis[y]>dis[x]+e[x][i].len)
{
dist[y]=dis[y];
dis[y]=dis[x]+e[x][i].len;
vis[y]=1,q.push(node{y,dis[y]});
}
else if(dist[y]>dis[x]+e[x][i].len && dis[x]+e[x][i].len!=dis[y])
{
dist[y]=dis[x]+e[x][i].len;
vis[y]=1,q.push(node{y,dis[y]});
}
if(dist[y]>dist[x]+e[x][i].len && dist[x]+e[x][i].len)
dist[y]=dist[x]+e[x][i].len;
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
n=read(),m=read();
for(int i=1;i<=m;++i)
{
int x=read(),y=read(),c=read();
e[x].push_back(edge{y,c});
e[y].push_back(edge{x,c});
}
dij();
printf("%d\n",dist[n]);
return 0;
}