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; 
}

  

posted @ 2019-09-18 15:22  EM-LGH  阅读(121)  评论(0编辑  收藏  举报