「Codeforces 632F」Magic Matrix

称一个矩阵为魔法矩阵,当且仅当满足一下三点:
1. 1 i , j n , a i , j = a j , i
2. 1 i n , a i , i = 0
3. 1 i , j , k n , a i , j max ( a i , k , a k , j )
询问一个矩阵是否为魔法矩阵
n 2500

将矩阵抽象成一个有 n 个点 n 2 条边的无向完全图,边权为 a i , j
f i , j 表示从 i 出发到 j 的所有路径上最长的边的最小值,显然 a i , j f i , j
根据题意,因为 a i , j max ( a i , k , a k , j ) ,而 a i , k max ( a i , l , a l , k ) ,所以 a i , j max ( a i , k 1 , a k 1 , k 2 . . . a k m , j ) ,即 a i , j f i , j
所以 a i , j = f i , j ,这样就只要用 M S T D F S 就可以在 O ( n 2 ) 判断条件了。

#include <cstdio>
#include <cstring>
#define Min(_A, _B) (_A < _B ? _A : _B)
#define Max(_A, _B) (_A > _B ? _A : _B)
#define R register
int n, a[2510][2510];
bool vis[2510]; int dis[2510], from[2510], Point[2510], Next[5010], To[5010], W[5010], q;
void Add(R int u, R int v, R int w)
{
    Next[++q] = Point[u]; Point[u] = q; To[q] = v; W[q] = w;
    Next[++q] = Point[v]; Point[v] = q; To[q] = u; W[q] = w;
}
bool DFS(R int u, R int from, R int pos, R int val)
{
    if(a[pos][u] != val) return 1; 
    for(R int j = Point[u]; j; j = Next[j]) if(To[j] != from && DFS(To[j], u, pos, Max(W[j], val))) return 1;
    return 0;
}
int main()
{
    scanf("%d", &n);
    for(R int i = 1; i <= n; ++i)
        for(R int j = 1; j <= n; ++j)
            scanf("%d", &a[i][j]);
    for(R int i = 1; i <= n; ++i)
        for(R int j = 1; j <= n; ++j)
            if(a[i][j] != a[j][i])
            {
                puts("NOT MAGIC");
                return 0;
            }
    memset(dis, 127, sizeof(dis)); dis[1] = 0;
    for(R int i = 1; i <= n; ++i)
    {
        R int pos = 0;
        for(R int j = 1; j <= n; ++j) if(!vis[j] && dis[pos] > dis[j]) pos = j;
        if(i > 1) Add(pos, from[pos], dis[pos]);
        vis[pos] = 1;
        for(R int j = 1; j <= n; ++j) if(!vis[j] && a[pos][j] < dis[j])
        { from[j] = pos; dis[j] = a[pos][j]; }
    }
    for(R int i = 1; i <= n; ++i) if(DFS(i, i, i, 0)){ puts("NOT MAGIC"); return 0; }
    puts("MAGIC");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/steaunk/article/details/80217764