洛谷P2243 电路维修

题目地址

转化为图论问题

对于每个交叉点(X,Y)抽象成节点。与它相邻的四个点中,可以直接连线的边权为0,否则边权为1

死了的SPFA解决图论问题。

 

#include <cstring>
#include <cstdio>
#define GC getchar()
#define Clean(X,K) memset(X,K,sizeof(X))
#define re register
#define Hash(X,Y) ((X)*(M+1)+(Y))
using namespace std ;
int Qread () {
    int X = 0 ;
    char C = GC ;
    while (C > '9' || C < '0') C = GC ;
    while (C >='0' && C <='9') {
        X = X * 10 + C - '0' ;
        C = GC ;
    }
    return X ;
}
const int Maxn = 505 , INF = 1061109567;
int Times , N , M , Head[Maxn * Maxn] , En = 0 , Q[Maxn * Maxn]  , Mdis[Maxn * Maxn],  Vis[Maxn * Maxn];
struct Edge {
    int From , Goto , NextEdge , Len ;
};
Edge E[Maxn * Maxn * 4] ;
void Adg (int X , int Y ,int L) {
    E[++En].From = X ;
    E[En].Goto = Y ;
    E[En].Len = L ;
    E[En].NextEdge = Head[X] ;
    Head[X] = En ;
}
int SPFA () {
    re int H = 1 , T = 1 ;
    Clean(Vis , 0) , Clean(Mdis , 0x3f) ;
    const int St = Hash(0 , 0) , Top = (N + 1) * (M + 1);
    if (++T > Top) T = 0 ;
    Q[T] = St , Mdis[St] = 0 , Vis[St] = 1 ;
    while (H != T) {
        if (++ H > Top) H = 0 ;
        const int Now = Q[H] ;
        Vis[Now] = 0 ;
        for (re int i = Head[Now ] ; i ; i = E[i].NextEdge ) {
            int Dis = Mdis[Now] + E[i].Len ;
            if (Dis < Mdis[E[i].Goto ]) {
                Mdis[E[i].Goto ] = Dis ;
                if (!Vis[E[i].Goto ]) {
                    Vis[E[i].Goto ] = 1 ;
                    if (++ T > Top) T = 0 ;
                    Q[T] = E[i].Goto ;
                }
            }
        }
    }
    return Mdis[Hash(N , M)] ;
}
int main () {
    //freopen ("P2243.in" , "r" , stdin) ;
    Times = Qread () ;
    while (Times -- ) {
        N = Qread () , M = Qread () ;
        Clean (Head , 0 ) , En = 0 ;
        for (re int i = 0 ; i < N ; ++ i) {
            for (re int j = 0 ; j < M; ++ j) {
                char C = GC ;
                while (C !='\\' && C !='/') C = GC ;
                if (C == '/') {
                    Adg (Hash(i + 1 , j + 1) , Hash (i , j) , 1) ;
                    Adg (Hash (i , j) ,Hash(i + 1 , j + 1) ,  1) ;
                    Adg (Hash(i + 1 , j) , Hash (i , j + 1) , 0) ;
                    Adg (Hash (i , j + 1) ,Hash(i + 1 , j)  , 0) ;
                } else if (C == '\\') {
                    Adg (Hash(i + 1 , j + 1) , Hash (i , j) , 0) ;
                    Adg (Hash (i , j) ,Hash(i + 1 , j + 1) ,  0) ;
                    Adg (Hash(i + 1 , j) , Hash (i , j + 1) , 1) ;
                    Adg (Hash (i , j + 1) ,Hash(i + 1 , j)  , 1) ;
                }
            }
        }
        int Ans = SPFA() ;
        if (Ans < INF)printf ("%d\n" , Ans) ;
        else printf ("NO SOLUTION\n") ;
    }
    fclose (stdin) , fclose (stdout) ;
    return 0 ;
}

 

 

 

 

转载于:https://www.cnblogs.com/bj2002/p/10491048.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值