题意:有n个城市,编号为1~n,每个城市都相互连通,其中有m对城市通过公路连通,其他的市通过铁路连通,经过公路的时间为a,经过铁路的时间为b,问从1到达n的时间最短为多少?
题解:
第一种情况 1-n由公路相连,则最短距离为min(a,仅有铁路构成的路)
第二种情况 1-n由铁路相连,则最短距离为min(a,仅有公路构成的路)
在一种情况中,应该bfs搜索没有用公路相连的点,且,一旦dis[n]>a就退出。
第二种情况 ,一个最短路即可。
#include<bits/stdc++.h>
using namespace std;
int n,m;
long long a,b;
const int maxn=500000+100;
int head[maxn],cnt=0;
long long min1,min2;
struct node
{
long long distance;
int point;
node(){}
node(int _point,int _distance)
{
point=_point;
distance=_distance;
}
friend bool operator <(node aa,node bb)
{
return aa.distance>bb.distance;
}
};
struct edge
{
int v,nxt;
long long w;
}edge[maxn*3+100];
void add_edge(int u,int v,long long w)
{
edge[cnt].v=v;
edge[cnt].nxt=head[u];
edge[cnt].w=w;
head[u]=cnt++;
}
long long dis[maxn];
int vis[maxn],viss[maxn];
long long diss[maxn];
void zyz(int u)
{
for(int i=1;i<=n;i++)
{
dis[i]=0x3f3f3f3f;
}
dis[u]=0;
memset(vis,0,sizeof(vis));
priority_queue<node>q;
q.push(node(u,dis[u]));
while(!q.empty())
{
node now;
now=q.top();
q.pop();
if(vis[now.point]==1)
continue;
vis[now.point]=1;
for(int i=head[now.point];i!=-1;i=edge[i].nxt)
{
int v=edge[i].v;
if(!vis[v])
{
if(dis[now.point]+edge[i].w<=b)
{
dis[v]=dis[now.point]+edge[i].w;
q.push(node(v,dis[v]));
}
else
{
return;
}
if(v==n)
{
return;
}
}
}
}
min1=dis[n];
}
void bfs(int u)
{
for(int i=1;i<=n;i++)
{
diss[i]=0x3f3f3f3f;
}
queue<int>q;
q.push(1);
diss[1]=0;
memset(vis,0,sizeof(vis));
memset(viss,0,sizeof(viss));
viss[1]=1;
while(!q.empty())
{
int now;
now=q.front();
q.pop();
for(int i=1;i<=n;i++)
{
vis[i]=0;
}
for(int i=head[now];i!=-1;i=edge[i].nxt)
{
int v=edge[i].v;
vis[v]=1;
}
for(int i=1;i<=n;i++)
{
if(vis[i]==0&&viss[i]==0)
{
if(diss[now]+b<=a)
{
diss[i]=diss[now]+b;
viss[i]=1;
q.push(i);
}
else
{
return;
}
if(i==n)
{
return;
}
}
}
}
min2=diss[n];
}
int main ()
{
while(~scanf("%d%d%lld%lld",&n,&m,&a,&b))
{
memset(head,-1,sizeof(head));
cnt=0;
int flag=0;
for(int i=1;i<=m;i++)
{
int xx,yy;
cin>>xx>>yy;
if(xx==1&&yy==n)
{
flag=1;
}
if(xx==n&&yy==1)
{
flag=1;
}
add_edge(xx,yy,a);
add_edge(yy,xx,a);
}
if(flag==1)
{
bfs(1);
printf("%lld\n",min(a,diss[n]));
}
else
{
zyz(1);
printf("%lld\n",min(b,dis[n]));
}
//printf("%lld\n",min(min1,min2));
}
}
方法二:用set处理bfs进入的点,使其只进入一次
set大法好
#include<bits/stdc++.h>
using namespace std;
int n,m;
set<int>st,ts;
set<int>::iterator it;
long long a,b;
const int maxn=500000+100;
int head[maxn],cnt=0;
long long min1,min2;
struct node
{
long long distance;
int point;
node(){}
node(int _point,int _distance)
{
point=_point;
distance=_distance;
}
friend bool operator <(node aa,node bb)
{
return aa.distance>bb.distance;
}
};
struct edge
{
int v,nxt;
long long w;
}edge[maxn*3+100];
void add_edge(int u,int v,long long w)
{
edge[cnt].v=v;
edge[cnt].nxt=head[u];
edge[cnt].w=w;
head[u]=cnt++;
}
long long dis[maxn];
int vis[maxn],viss[maxn];
long long diss[maxn];
void zyz(int u)
{
for(int i=1;i<=n;i++)
{
dis[i]=0x3f3f3f3f;
}
dis[u]=0;
memset(vis,0,sizeof(vis));
priority_queue<node>q;
q.push(node(u,dis[u]));
while(!q.empty())
{
node now;
now=q.top();
q.pop();
if(vis[now.point]==1)
continue;
vis[now.point]=1;
for(int i=head[now.point];i!=-1;i=edge[i].nxt)
{
int v=edge[i].v;
if(!vis[v])
{
if(dis[v]>dis[now.point]+edge[i].w)
{
dis[v]=dis[now.point]+edge[i].w;
q.push(node(v,dis[v]));
}
}
}
}
}
void bfs(int u)
{
for(int i=1;i<=n;i++)
{
diss[i]=0x3f3f3f3f;
}
queue<int>q;
q.push(1);
diss[1]=0;
st.clear();
ts.clear();
for(int i=2;i<=n;i++)
{
st.insert(i);
}
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=head[now];i!=-1;i=edge[i].nxt)
{
int v=edge[i].v;
if(st.count(v)==0)
{
continue;
}
st.erase(v);
ts.insert(v);
}
for(it=st.begin();it!=st.end();it++)
{
q.push(*it);
diss[*it]=diss[now]+b;
}
st.swap(ts);
ts.clear();
}
}
int main ()
{
while(~scanf("%d%d%lld%lld",&n,&m,&a,&b))
{
memset(head,-1,sizeof(head));
cnt=0;
int flag=0;
for(int i=1;i<=m;i++)
{
int xx,yy;
cin>>xx>>yy;
if(xx==1&&yy==n)
{
flag=1;
}
if(xx==n&&yy==1)
{
flag=1;
}
add_edge(xx,yy,a);
add_edge(yy,xx,a);
}
if(flag==1)
{
bfs(1);
printf("%lld\n",min(a,diss[n]));
}
else
{
zyz(1);
printf("%lld\n",min(b,dis[n]));
}
//printf("%lld\n",min(min1,min2));
}
}