(Educational Codeforces Round 9)Magic Matrix(最小生成树)

Magic Matrix

time limit per test5 seconds
memory limit per test512 megabytes
inputstandard input
outputstandard output
You’re given a matrix A of size n × n.

Let’s call the matrix with nonnegative elements magic if it is symmetric (so aij = aji), aii = 0 and aij ≤ max(aik, ajk) for all triples i, j, k. Note that i, j, k do not need to be distinct.
Determine if the matrix is magic.

Input

The first line contains integer n (1 ≤ n ≤ 2500) — the size of the matrix A.

Each of the next n lines contains n integers aij (0 ≤ aij < 109) — the elements of the matrix A.

Note that the given matrix not necessarily is symmetric and can be arbitrary.

Output

Print ”MAGIC” (without quotes) if the given matrix A is magic. Otherwise print ”NOT MAGIC”.

Examples

input

3
0 1 2
1 0 2
2 2 0

output

MAGIC

input

2
0 1
2 3

output

NOT MAGIC

input

4
0 1 2 3
1 0 3 4
2 3 0 5
3 4 5 0

output

NOT MAGIC


题意

给你一个n*n的矩阵,然后判断是否是magic的
什么是magic的呢?只要a[i][j]=a[j][i],a[i][i]=0,a[i][j]<=max(a[i][k],a[k][j])对于所有的k。

题解:
把这个矩阵抽象成一个完全图
然后这个完全图,a[i][j]表示i点向j点连一条a[i][j]的边
然后magic是什么意思呢?
就是任何一条路径中的最大边都大于等于a[i][j],那么翻译过来就是跑最小生成树的之后,i到j上的最大边大于等于a[i][j]。


#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
const int N = 2510;
int a[N][N];
vector<pair<int, int> > v;
bitset<N> b[N];

int main() {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            scanf("%d", &a[i][j]);
            v.push_back(make_pair(a[i][j], i * n + j));
        }
        if (a[i][i] != 0){ 
            printf("NOT MAGIC\n");
            return 0;
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (a[i][j] != a[j][i]) {
                printf("NOT MAGIC\n");
                return 0;
            }
        }
    }
    sort(v.begin(), v.end());
    int l = 0;
    for (int k = 0; k < v.size(); k++) {
        int i = v[k].y / n, j = v[k].y % n;
        if ((b[i] & b[j]).any()) {
            printf("NOT MAGIC\n");
            return 0;
        }
        if (k != v.size() - 1 && v[k].x != v[k + 1].x) {
            for (; l <= k; l++){
                b[v[l].y / n][v[l].y % n] = 1;
                b[v[l].y / n][v[l].y % n] = 1;
            }
        }
    }
    printf("MAGIC\n");
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值