P1811
模拟赛读错题了,读错后的题意就是这道题,写完后发现没有相同思路的,所以写篇题解纪念一下。
由于是无权最短路,所以考虑 bfs,但是只用 bfs 我们无法判定这样走能否满足限制。
于是考虑升维,我们设
发现这样做有
我们发现,bfs 时有非常多相同的转移,比如在
不过我的实现中用了 map 所以实际会多一个
代码:
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f,MOD=1e9+7;
#define iosize 1048576
char *p1,*p2,buf[iosize];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,iosize,stdin),p1==p2)?EOF:*p1++)
inline int read()
{
int x=0,f=1;
char ch=nc();
while(ch<48||ch>57)
{
if(ch=='-')
f=-1;
ch=nc();
}
while(ch>=48&&ch<=57)
x=x*10+ch-48,ch=nc();
return x*f;
}
const int N=5e5+10;
int n,m,q;
int tot;
int head[N];
struct edge{int v,nxt;}e[4*N];
void add(int u,int v)
{
tot++;
e[tot]={v,head[u]};
head[u]=tot;
}
map<int,int> pre[N];
map<int,int> dis[N];
map<pair<int,pair<int,int> > ,bool> mp;
void bfs(int u,int fa)
{
queue<pair<int,int> > q;
dis[u][fa]=1;
q.push(make_pair(u,fa));
while(q.size())
{
int u=q.front().first;
int fa=q.front().second;
q.pop();
for(int lst=0,i=head[u];i;i=e[i].nxt)
{
int v=e[i].v;
int t=lst;
lst=i;
if(mp.count(make_pair(fa,make_pair(u,v)))) continue;
if(t==0) head[u]=e[i].nxt;//用链式前向星删掉这条边
else e[t].nxt=e[i].nxt;
lst=t;
if(dis[v].count(u)) continue;
pre[v][u]=fa;
dis[v][u]=dis[u][fa]+1;
q.push(make_pair(v,u));
}
}
}
signed main()
{
n=read(),m=read(),q=read();
for(int i=1;i<=m;i++)
{
int u,v;
u=read(),v=read();
add(u,v);
add(v,u);
}
for(int i=1;i<=q;i++)
{
int u,v,w;
u=read(),v=read(),w=read();
mp[make_pair(u,make_pair(v,w))]=true;
}
bfs(1,0);
int ans=INF;
int res=0;
for(auto e:dis[n])
{
if(e.second<ans) ans=e.second,res=e.first;
}
cout<<ans-1<<endl;
vector<int> Ans;
int now=n;
int t=res;
while(now)
{
Ans.push_back(now);
int x=t;
t=pre[now][t];
now=x;
}
for(int i=Ans.size()-1;i>=0;i--) cout<<Ans[i]<<" ";
return 0;
}