Atcoder Code Festival 2016 Qual A D - マス目と整数 / Grid and Integers

大家都很强, 可与之共勉 。

一道好题,嗯。
题意
给出一个R*C的棋盘.共有R行C列,R*C个格子.现要在每个格子都填一个非负整数.使得任意一个2*2的正方形区域都满足这样的性质:左上角的数字+右下角的数字=左下角的数字+右上角的数字.有些格子已经确定,你不能更改其中的数字.其他格子的数字由你决定.A想要知道一个可行的填充棋盘的方案.但是这个方案可能很大.所以你只需对给定的棋盘判定是否存在至少一种可行的填充棋盘的方案.

题目链接

Bfs或者Dfs判矛盾,主要注意对于任意一列,任意两行之间元素的差相等。任意一行同样。,且解都为非负整数。

#include <bits/stdc++.h>

# define Size 1000000

inline int readInt ( )  {
    register int x, c ;
    static char buf [Size], *ss, *tt ;
    # define pick( ) ( (ss == tt) ? ( tt = buf + fread ( ss = buf, 1, Size, stdin ), ( ss == tt ) ? -1 : *ss ++ ) : *ss ++ )
    while ( ! isdigit ( c = pick ( ) ) ) ;
    for ( x = -48 + c ; isdigit ( c = pick ( ) ) ; x = x * 10 + c - 48 ) ;
    return x ;
    # undef pick
}

inline void smin ( long long& d, long long x )  {  ( d > x ) ? d = x : 0 ;  }

const long long inf = ( ~0ull >> 1 ) ;
const int N = 200010 ;

int q [N] ;
bool inq [N] ;
long long a [N] ;

struct edge  {
    int to, w ; edge* nxt ;
} g [N], *head [N], *NewEdge ;

int main ( )  {
    int h, w, n ;
    h = readInt ( ), w =  readInt ( ), n = readInt ( ) ;
    NewEdge = g ;
    for ( int i = 0 ; i < n ; ++ i )  {
        int x = readInt ( ), y = readInt ( ), z = readInt ( ) ;
        -- x, -- y ;
        *( ++ NewEdge ) = ( edge ) {  h + y, z, head [x]  } ; head [x] = NewEdge ;
        *( ++ NewEdge ) = ( edge ) {  x, z, head [h + y]  } ; head [h + y] = NewEdge ;
    }
    for ( int i = 0, l = h + w ; i < l ; ++ i )  {
        if ( ! inq [i] )  {
            register edge* it ;
            register int fr ( 0 ), tl ( 0 ) ;
            a [i] = 0 ;
            q [++ tl] = i ;
            inq [i] = true ;
            while ( fr ^ tl )  {
                int u = q [++ fr] ;
                for ( it = head [u] ; it ; it = it -> nxt )  {
                    int r = it -> to, v = it -> w ;
                    if ( inq [r] )  {
                        if ( a [u] + a [r] != v )  {
                            return puts ( "No" ), 0 ;
                        }
                        continue ;
                    }
                    q [++ tl] = r ;
                    inq [r] = true ;
                    a [r] = v - a [u] ;
                }
            }
            long long m1 = inf, m2 = inf ;
            while ( tl )  {
                ( q [tl] < h ) ? smin ( m1, a [q [tl --]] ) : smin ( m2, a [q [tl --]] ) ;
            }
            if ( m1 + m2 < 0 )  {
                return puts ( "No" ), 0 ;
            }
        }
    }
    return puts ( "Yes" ), 0 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值