【题解】P2243 电路维修 双端队列搜索
建边,不转就能联通的建0,需要转才能联通的建1
在一张边权只有0/1的图上,可以用双端队列bfs
0边从队头入队,1边从队尾入队
code
1 #include<bits/stdc++.h> 2 using namespace std; 3 namespace gengyf{ 4 #define ll long long 5 #define mp make_pair 6 #define fir first 7 #define sec second 8 const int maxn=510; 9 inline int read(){ 10 int x=0,f=1;char s=getchar(); 11 while(s<'0'||s<'9'){if(s=='-')f=-1;s=getchar();} 12 while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} 13 return f*x; 14 } 15 deque<pair<int,int> > q; 16 vector<pair<pair<int,int>,int> > p[maxn][maxn]; 17 int T,n,m,dis[maxn][maxn],vis[maxn][maxn]; 18 char a[maxn][maxn]; 19 inline void add(int a,int b,int x,int y,int z){ 20 p[a][b].push_back(mp(mp(x,y),z)); 21 } 22 int main(){ 23 scanf("%d",&T); 24 while(T--){ 25 scanf("%d%d",&n,&m); 26 for(int i=1;i<=n;i++){ 27 scanf("%s",a[i]+1); 28 } 29 for(int i=0;i<=n;i++) 30 for(int j=0;j<=m;j++){ 31 p[i][j].clear(); 32 } 33 for(int i=1;i<=n;i++) 34 for(int j=1;j<=m;j++){ 35 if(a[i][j]=='/'){ 36 add(i-1,j-1,i,j,1); 37 add(i,j,i-1,j-1,1); 38 add(i,j-1,i-1,j,0); 39 add(i-1,j,i,j-1,0); 40 } 41 else { 42 add(i-1,j-1,i,j,0); 43 add(i,j,i-1,j-1,0); 44 add(i,j-1,i-1,j,1); 45 add(i-1,j,i,j-1,1); 46 } 47 } 48 memset(dis,0x3f,sizeof(dis)); 49 dis[0][0]=0; 50 memset(vis,0,sizeof(vis)); 51 q.clear(); 52 q.push_back(mp(0,0)); 53 while(!q.empty()){ 54 int x=q.front().fir,y=q.front().sec; 55 q.pop_front(); 56 vis[x][y]=1; 57 if(x==n&&y==m){ 58 printf("%d\n",dis[x][y]); 59 goto end; 60 } 61 for(int i=0;i<p[x][y].size();i++){ 62 int xx=p[x][y][i].fir.fir; 63 int yy=p[x][y][i].fir.sec; 64 int z=p[x][y][i].sec; 65 if(vis[xx][yy])continue; 66 if(dis[xx][yy]>dis[x][y]+z){ 67 dis[xx][yy]=dis[x][y]+z; 68 if(z){ 69 q.push_back(mp(xx,yy)); 70 } 71 else { 72 q.push_front(mp(xx,yy)); 73 } 74 } 75 } 76 } 77 puts("NO SOLUTION"); 78 end:; 79 } 80 return 0; 81 } 82 } 83 signed main(){ 84 gengyf::main(); 85 return 0; 86 }