题解:P14726 [ICPC 2022 Seoul R] Forbidden Turns
睡不着起来写一道题。
思路:
本题最麻烦的一个地方在于可以重复经过一个结点。这意味着我们的
实现就用 map 套 pair。pair 中存当前结点的前驱结点和当前结点。
接下来是怎么判断不合法的转弯。题目的意思大致是给你几个三元组
#define pii pair<int,int>
map<pii,set<int> > f;
这里的 pair 存
跑完最短路我们遍历一遍
::::info[代码]
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
const int ri=1e6+5;
bool vis[ri];
int n,m,k,s,t,head[ri],tot;
map<pii,set<int> > f;
map<pii,int> dis;//dis[mp(u,v)]:走到v这个结点,前驱结点是u的最短距离
struct edge{
int nxt,to,val;
}e[ri];
struct node{
int u,dis,pre;
bool operator<(const node &t)const{
return t.dis<dis;
}
};
void add(int u,int v,int w){
e[++tot]={head[u],v,w};
head[u]=tot;
}
void dijkstra(int s){
priority_queue<node> q;
q.push({s,0,-1});
dis[mp(-1,s)]=0;//前驱结点初始化为-1(顶点编号 0-n-1)
while(q.size()){
node t=q.top();
q.pop();
int u=t.u,pre=t.pre;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to,w=e[i].val;
if(f[mp(pre,u)].count(v)) continue;//pre->u->v 不合法
if(!dis.count(mp(u,v))||dis[mp(u,v)]>t.dis+w){//map不好初始化,所以要额外判一下是不是不存在
dis[mp(u,v)]=t.dis+w;
q.push({v,dis[mp(u,v)],u});
}
}
}
}
int main(){
scanf("%d%d%d%d%d",&m,&n,&k,&s,&t);
for(int i=1,u,v,w;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
for(int i=1,u,v,w;i<=k;i++){
scanf("%d%d%d",&u,&v,&w);
f[mp(u,v)].insert(w);//存不能转弯的边
}
dijkstra(s);
int ans=0x3f3f3f3f;
for(auto [u,dis]:dis){
if(u.second==t) ans=min(ans,dis);//统计走到t结点的全部方案取最优
}
if(ans==0x3f3f3f3f){
puts("-1");
return 0;
}
printf("%d\n",ans);
return 0;
}
::::
哪里讲的不清晰,或是不理解的可以在评论区问我。