电路维修 --- 双端队列bfs

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27121257/article/details/82217328

传送门:洛谷P2243


题目描述

这里写图片描述


分析

初步判断,是道最短路的题.
  首先就是建图了,对于电路板上的每一对角线,令与读入方向相同的路径边权为0,方向相反的边权为1.
  由于只能走斜线,根据网格图的性质可知横纵坐标之和为奇数的点是到不了的,默认起点为 ( 0 , 0 ) (0, 0) ,对此,可以去掉一半的边(根本就到不了),同时也可以直接判断无解的情况
  跑图的话,dijkstra + heap,和经过优化的spfa(关于spfa,他$ \cdots $)应该是能过的,但由于边权只有0和1,所以只要考虑用双端队列的bfs,即可(类似于spfa的SLF优化), 若边权为1,则将其放入队尾,否则置于队首,要注意的是,一个点可能多次入队


代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>

#define IL inline

using namespace std;

IL int read()
{
    char c = getchar();
    int sum = 0 ,k = 1;
    for(;'0' > c || c > '9'; c = getchar())
        if(c == '-') k = -1;
    for(;'0' <= c && c <= '9'; c = getchar()) sum = sum * 10 + c - '0';
    return sum * k;
}

int to[502005], nxt[502005], val[502005];
int last[251005];
int cnt;
IL void add(int u, int v, int w)
{
    //printf("%d %d %d\n", u, v, w);
    to[++cnt] = v; nxt[cnt] = last[u]; val[cnt] = w; last[u] = cnt;
    to[++cnt] = u; nxt[cnt] = last[v]; val[cnt] = w; last[v] = cnt;
}

int S, T;
int n, m;

int dis[251005];

IL int turn(int x, int y)
{	
    return x * (m + 1) + y + 1;
}

IL void bfs(int u)
{
    memset(dis, -1, sizeof(dis));
    dis[u] = 0;
    deque<int>Q;
    Q.push_back(u);
    if(S == T) { printf("0\n"); return ; }
    for(; !Q.empty();)
    {
        u = Q.front(); Q.pop_front();
        for(int i = last[u], v; (v = to[i]); i = nxt[i])
        if(dis[v] == -1 || dis[u] + val[i] < dis[v])
        {	
            dis[v] = dis[u] + val[i];
            //printf("%d %d %d %d\n", u, v, dis[u], dis[v]);
            if(v == T) { printf("%d\n", dis[v]); return ; }
            if(!val[i]) Q.push_front(v); else Q.push_back(v);
        }
    }
}

int main()
{
    for(int k = read(); k; --k)
    {
        cnt = 0;
        memset(last, 0, sizeof(last));
    	n = read(); m = read();
    	char c;
    	for(int i = 0; i < n; ++i)
   		for(int j = 0; j < m; ++j)
    	{
    		scanf(" %c", &c);
    		if((i + j) & 1) add(turn(i, j + 1), turn(i + 1, j), c == '\\');
    		else add(turn(i, j), turn(i + 1, j + 1), c == '/');
    	}
    	if((n + m) & 1) { printf("NO SOLUTION\n"); continue; }
    	S = 1; T = turn(n, m);
    	bfs(S);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_27121257/article/details/82217328
今日推荐