bzoj2346[Baltic 2011]Lamp*

bzoj2346[Baltic 2011]Lamp

题意:

给出一个像下图一样的电路图,长为n,宽为m,求最少将几个"\"改成"/"或将"/"改成"\"使左上角和左下角联通。n,m<=500

题解:

如果某格是/,则左上角和右下角连边,长度为0,左下角和右上角连边,长度为1;如果某格是\,则左上角和右下角连边,长度为1,左下角和右上角连边,长度为0,然后求最短路即可。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <queue>
 5 #define inc(i,j,k) for(int i=j;i<=k;i++)
 6 #define maxn 300010
 7 #define INF 0x3fffffff
 8 using namespace std;
 9 
10 char str[maxn]; struct e{int t,w,n;}es[maxn*4]; int g[maxn],ess;
11 void pe(int f,int t,int w){
12     es[++ess]=(e){t,w,g[f]}; g[f]=ess; es[++ess]=(e){f,w,g[t]}; g[t]=ess;
13 }
14 int n,m;
15 struct nd{int d,u; bool operator < (const nd &a)const{return d>a.d;}};
16 int d[maxn]; bool vis[maxn]; priority_queue<nd>q;
17 void dijkstra(int s,int t){
18     inc(i,s,t)d[i]=INF; d[s]=0; q.push((nd){0,s});
19     while(!q.empty()){
20         int x; while(!q.empty()&&vis[x=q.top().u])q.pop(); if(vis[x])break; vis[x]=1;
21         for(int i=g[x];i;i=es[i].n)if(d[es[i].t]>d[x]+es[i].w){
22             d[es[i].t]=d[x]+es[i].w; q.push((nd){d[es[i].t],es[i].t});
23         }
24     }
25 }
26 int main(){
27     scanf("%d",&n); scanf("%d",&m);
28     inc(i,1,n){
29         scanf("%s",str+1);
30         inc(j,1,m){
31             if(str[j]=='\\')pe((i-1)*(m+1)+j,i*(m+1)+j+1,0),pe((i-1)*(m+1)+j+1,i*(m+1)+j,1);
32             else pe((i-1)*(m+1)+j,i*(m+1)+j+1,1),pe((i-1)*(m+1)+j+1,i*(m+1)+j,0);
33         }
34     }
35     dijkstra(1,(n+1)*(m+1));
36     d[(n+1)*(m+1)]==INF?printf("NO SOLUTION"):printf("%d",d[(n+1)*(m+1)]); return 0;
37 }

 

20161111

posted @ 2016-11-13 16:01  YuanZiming  阅读(164)  评论(0编辑  收藏  举报