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