BZOJ 2346: [Baltic 2011]Lamp Dijkstra
不难发现如果一个边的方向改变,就一定不会改回来(这样肯定不是最短路).
所以就直接建双向边,边权为 $0$ 代表不改变,边权为 $1$ 代表改变,跑一个最短路即可.
#include <bits/stdc++.h> #define N 600 #define M 1000000 #define inf 1000000000 #define setIO(s) freopen(s".in","r",stdin) using namespace std; char str[N]; int id[N][N],tot,edges,s; int hd[M],to[M],nex[M],val[M],done[M],d[M]; void addedge(int u,int v,int c) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c; swap(u,v); nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c; } struct P { int u,dis; P(int u=0,int dis=0):u(u),dis(dis){} bool operator<(P b) const { return b.dis<dis; } }; priority_queue<P>q; void Dijkstra() { for(int i=0;i<M;++i) d[i]=inf; for(d[s]=0,q.push(P(s,0));!q.empty();) { P e=q.top(); q.pop(); int u=e.u; if(done[u]) continue; done[u]=1; for(int i=hd[u];i;i=nex[i]) { int v=to[i]; if(d[v]>d[u]+val[i]) { d[v]=d[u]+val[i]; q.push(P(v,d[v])); } } } } int main() { // setIO("input"); int n,m,i,j; scanf("%d%d",&n,&m); for(i=1;i<=n+1;++i) for(j=1;j<=m+1;++j) id[i][j]=++tot; for(i=1;i<=n;++i) { scanf("%s",str+1); for(j=1;j<=m;++j) { if(str[j]=='/') { addedge(id[i+1][j],id[i][j+1],0); addedge(id[i][j],id[i+1][j+1],1); } else { addedge(id[i][j],id[i+1][j+1],0); addedge(id[i+1][j],id[i][j+1],1); } } } s=id[1][1]; int t=id[n+1][m+1]; Dijkstra(); if(d[t]==inf) printf("NO SOLUTION\n"); else printf("%d\n",d[t]); return 0; }