题解 CF229B 【Planets】
一道最短路,与模板不同的是这里多了一个判断条件:
当有其他人在使用这个星球的传送通道时,Jack无法离开这个星球。
最开始想到开一个二维数组存当前星球的传送门使用情况。
#include<bits/stdc++.h>
#define FOR(i,j,k) for(int i=(j);i<=(k);i++)
using namespace std;
int n,m,cnt,Time;
int dis[100001];
bool inq[100001];
int h[100001],t[100001],nxt[100001],val[100001];
int used[100001][1001];
int f,e,q[1000001];
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
inline void addedge(int a,int b,int c)
{
t[++cnt]=b,val[cnt]=c,nxt[cnt]=h[a],h[a]=cnt;
}
inline bool check(int Time,int planet)
{
int i=0;
while(used[planet][++i]!=0)
{
if(used[planet][i]==Time) return true;
if(used[planet][i]>Time) return false;
}
return false;
}
int main()
{
n=read(),m=read();
memset(dis,-1,sizeof(dis));
memset(h,0,sizeof(h));
memset(inq,false,sizeof(inq));
for(int i=1;i<=m;i++)
{
int u=read(),v=read(),w=read();
addedge(u,v,w),addedge(v,u,w);
}
for(int i=1;i<=n;i++)
{
int tmp=read();
for(int j=1;j<=tmp;j++)
used[i][j]=read();
}
inq[1]=true,dis[1]=0,q[1]=1,f=e=1;
while(f<=e)
{
int u=q[f++];
Time=dis[u];
while(check(Time,u)) Time++;
for(int p=h[u];p;p=nxt[p])
{
int v=t[p],c=val[p];
if(dis[v]==-1||dis[v]>=Time+c)
{
dis[v]=Time+c;
if(!inq[v]) inq[v]=true,q[++e]=v;
}
}
inq[u]=false;
}
printf("%d\n",dis[n]);
return 0;
}
然后发现开不下,直接 \(MLE\)。
于是想到 \(STL\) 的 \(map\)。
第一次写成这个样子,没过 \(#4\)。
#include<bits/stdc++.h>
#define FOR(i,j,k) for(int i=(j);i<=(k);i++)
using namespace std;
int n,m,cnt;
int dis[100001];
bool inq[100001];
int h[100001],t[100001],nxt[200001],val[200001];
int f,e,q[10000001];
map<int,int> s[100001];
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
inline void addedge(int a,int b,int c)
{
t[++cnt]=b,val[cnt]=c,nxt[cnt]=h[a],h[a]=cnt;
}
inline bool check(int Time,int planet)
{
int i=0;
while(s[planet][++i]!=0)
{
if(s[planet][i]==Time) return true;
if(s[planet][i]>Time) return false;
}
return false;
}
int main()
{
n=read(),m=read();
memset(dis,-1,sizeof(dis));
memset(h,0,sizeof(h));
for(int i=1;i<=m;i++)
{
int u=read(),v=read(),w=read();
addedge(u,v,w),addedge(v,u,w);
}
for(int i=1;i<=n;i++)
{
int tmp=read();
for(int j=1;j<=tmp;j++)
s[i][j]=read();
}
inq[1]=true,dis[1]=0,q[1]=1,f=e=1;
while(f<=e)
{
int u=q[f++];
int Time=dis[u];
while(check(Time,u)) Time++;
for(int p=h[u];p;p=nxt[p])
{
int v=t[p],c=val[p];
if(dis[v]==-1||dis[v]>=Time+c)
{
dis[v]=Time+c;
if(!inq[v]) inq[v]=true,q[++e]=v;
}
}
inq[u]=false;
}
printf("%d\n",dis[n]);
return 0;
}
再换一种方法,把 \(map\) 改成 \(bool\) 的就过了
中间 \(t\) 数组开错大小一直没过。
#include<bits/stdc++.h>
#define FOR(i,j,k) for(int i=(j);i<=(k);i++)
using namespace std;
int n,m,cnt;
int dis[100001];
bool inq[100001];
int h[100001],t[200001],nxt[200001],val[200001];
int f,e,q[10000001];
map<int,bool> s[100001];
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
inline void addedge(int a,int b,int c)
{
t[++cnt]=b,val[cnt]=c,nxt[cnt]=h[a],h[a]=cnt;
}
int main()
{
n=read(),m=read();
memset(dis,-1,sizeof(dis));
memset(h,0,sizeof(h));
for(int i=1;i<=m;i++)
{
int u=read(),v=read(),w=read();
addedge(u,v,w),addedge(v,u,w);
}
for(int i=1;i<=n;i++)
{
int tmp=read(),x;
for(int j=1;j<=tmp;j++)
x=read(),s[i][x]=true;
}
inq[1]=true,dis[1]=0,q[1]=1,f=e=1;
while(f<=e)
{
int u=q[f++];
int Time=dis[u];
while(s[u][Time]==true) Time++;//唯一要注意的点
for(int p=h[u];p;p=nxt[p])
{
int v=t[p],c=val[p];
if(dis[v]==-1||dis[v]>=Time+c)
{
dis[v]=Time+c;
if(!inq[v]) inq[v]=true,q[++e]=v;
}
}
inq[u]=false;
}
printf("%d\n",dis[n]);
return 0;
}
用的是 \(SPFA\)

浙公网安备 33010602011771号