您的位置:首页 > 其它

POJ 2449 Remmarguts' Date(k短路)

2017-11-07 20:06 246 查看

题面

题意

给出一幅有向图,求出其中的第k短路

方法

首先应该想到用BFS加上优先队列,按照距离由短到长进行搜索,当到达终点次数达到k次时停止.

代码(错误)

#include<iostream&g
4000
t;
#include<cstdio>
#include<cstring>
#include<queue>
#define ll long long
#define P pair<ll,ll>
#define fi first
#define se second
#define N 1010
#define M 100100
using namespace std;

struct Bn
{
ll next,to,time;
}bn[M];
ll n,m,k,first
,bb,s,t;
priority_queue<P,vector<P>,greater<P> >pq;
P tmp;

void add(ll u,ll v,ll w)
{
bb++;
bn[bb].to=v;
bn[bb].next=first[u];
bn[bb].time=w;
first[u]=bb;
}

int main()
{
ll i,j,p,q,o;
P now;
memset(first,-1,sizeof(first));
for(;!pq.empty();pq.pop());
cin>>n>>m;
for(i=1;i<=n;i++)
{
scanf("%lld%lld%lld",&p,&q,&o);
add(p,q,o);
}
cin>>s>>t>>k;
tmp.fi=0;
tmp.se=s;
pq.push(tmp);
for(;!pq.empty();)
{
tmp=pq.top();
pq.pop();
if(tmp.se==t)
{
if(k==1)
{
printf("%lld",tmp.first);
return 0;
}
k--;
}
now=tmp;
p=first[now.se];
for(;p!=-1;p=bn[p].next)
{
tmp.fi=now.fi+bn[p].time;
tmp.se=bn[p].to;
pq.push(tmp);
}
}
printf("-1");
return 0;
}


这种方法有以下缺点:

1.上述思路占用空间过大,会爆队列

2.当遇到无法到达终点时的情况就会陷入死循环

我们先解决第二个问题

要求k短路,则每个点最多扫过k次,因而我们可以记录每个点走过的次数,若超过k则跳过这个点,则不仅可解决上述问题,还能起到剪枝作用

对于第一个问题则需要改变排序的方式,因为目标是t,则可以根据到达t的最短需要长度进行排序,而不是根据已经经过路径,若根据已经经过路径长度排序,则可能会多次搜索离t较远的点,浪费大量空间.

为了计算出到达t的最短路,可以以t为起点,用迪杰斯特拉算出每一点到达它的最小距离(因点数少,边数多,可以用邻接矩阵),重定义一下小于号即可.

另外还要注意当起点和终点重合时,应该让k+1,因为一开始到达的那一次不算

代码(正解)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define N 2010
#define M 200200
#define INF 0x3f3f3f3f
using namespace std;

int n,m,k,first
,bb,s,t,cnt
,d
,mm

;
struct Bn
{
int next,to,time;
} bn[M];
struct Dn
{
int len,pos;
bool operator < (const Dn &u) const
{
return len + d[pos] > u.len + d[u.pos];
}
};
priority_queue<Dn>pq;
bool vis
;
Dn tmp,now;

inline void add(int u,int v,int w)
{
bb++;
bn[bb].to=v;
bn[bb].next=first[u];
bn[bb].time=w;
first[u]=bb;
}

inline void gx(int u)
{
int i;
for(i=1; i<=n; i++)
{
if(vis[i]) continue;
if(d[i]>mm[i][u]+d[u])
{
d[i]=mm[i][u]+d[u];
}
}
}

inline void get()
{
int i,j,l,mn;
d[t]=0;
vis[t]=1;
gx(t);
for(i=1; i<=n; i++)
{
mn=INF;
l=0;
for(j=1; j<=n; j++)
{
if(vis[j]) continue;
if(d[j]<mn)
{
l=j;
mn=d[j];
}
}
if(!l) return;
vis[l]=1;
gx(l);
}
}

int main()
{
//  freopen("1.txt","r",stdin);
int i,j,p,q,o;
memset(first,-1,sizeof(first));
memset(d,INF,sizeof(d));
memset(mm,INF,sizeof(mm));
for(;!pq.empty();pq.pop());
scanf("%d%d",&n,&m);
for(i=1; i<=m; i++)
{
scanf("%d%d%d",&p,&q,&o);
add(p,q,o);
mm[p][q]=min(mm[p][q],o);
}
scanf("%d%d%d",&s,&t,&k);
k+= s==t;
get();

if(!vis[s])
{
printf("-1\n");
return 0;
}

tmp.pos=s;
tmp.len=0;
pq.push(tmp);
for(; !pq.empty();)
{
now=pq.top();
pq.pop();
cnt[now.pos]++;
if(cnt[t]==k)
{
printf("%d\n",now.len);
return 0;
}
if(cnt[now.pos]>k) continue;
for(p=first[now.pos] ; p!=-1; p=bn[p].next)
{
tmp.len=now.len+bn[p].time;
tmp.pos=bn[p].to;
pq.push(tmp);
}
}
printf("-1\n");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: