codeforces 632F

題目大意

給定一個矩陣A ,大小是nn,n2500 ,判斷這個矩陣是否是Magic 的。
一個矩陣是Magic 的,必須滿足。
1.ai,i=0
2.ai,j=aj,i
3. 對於i,j,k 滿足ai,jmax(ai,k,aj,k)

解題思路

我們不妨把ai,j 看做在一個圖中ij 有一條長度爲ai,j 的雙向邊。這樣就可以滿足條件1和條件2。我們可以設fi,jij 的任意路徑的最長邊的最小值,可得ai,jfi,j .

假設一個矩陣滿足條件,則ai,jmax(ai,k1,ak1,j) ,ai,k1max(ai,k2,ak2,k1) ……,把式子代入可以發現,ai,jmax(ai,k1,ak1,k2,ak2,k3...,akm,j)=fi,j .

ai,j=fi,j .

判斷矩陣是否合法,就是判斷圖上的ij 的任意路徑的最長邊的最小值是否等於ai,j .

這個可以用MST實現。

參考代碼

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define maxn 2505
#define maxsq 15
using namespace std;

int a[maxn][maxn];

int f[maxn];

int head[maxn],t[maxn*2],v[maxn*2],next[maxn*2],sum;

int deep[maxn],fa[maxn][maxsq][2];

struct note{
    int x,y,len;
}s[maxn*maxn];

int n,tot;

int read(){
    int ret=0,ff=1;
    char ch=getchar();
    while (ch<'0'||ch>'9') {
        if (ch=='-') ff=-1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9') {
        ret=ret*10+ch-'0';
        ch=getchar();
    }
    return ret*ff;
}

int getf(int x){
    return f[x]==x ? f[x] : f[x]=getf(f[x]);
}

bool cmp(note i,note j){
    return i.len<j.len;
}

void insert(int x,int y,int z){
    t[++sum]=y;
    v[sum]=z;
    next[sum]=head[x];
    head[x]=sum;
}

void dfs(int x,int father) {
    deep[x]=deep[father]+1;
    for(int tmp=head[x];tmp;tmp=next[tmp]) {
        if (t[tmp]==father) continue;
        fa[t[tmp]][0][0]=x;
        fa[t[tmp]][0][1]=v[tmp];
        dfs(t[tmp],x);
    }
}

int calc(int x,int y){
    int ret=0;
    if (deep[x]<deep[y]) swap(x,y);
    fd(i,12,0)
        if (deep[fa[x][i][0]]>=deep[y]) {
            ret=max(ret,fa[x][i][1]);
            x=fa[x][i][0];
        }
    if (x==y) return ret;
    fd(i,12,0) 
        if (fa[x][i][0]!=fa[y][i][0]) {
            ret=max(ret,fa[x][i][1]);
            x=fa[x][i][0];
            ret=max(ret,fa[y][i][1]);
            y=fa[y][i][0];
        }
    ret=max(ret,fa[x][0][1]);
    ret=max(ret,fa[y][0][1]);
    return ret;
}

int main(){
    n=read();
    fo(i,1,n)
        fo(j,1,n) {
            a[i][j]=read();
            s[(i-1)*n+j].x=i;
            s[(i-1)*n+j].y=j;
            s[(i-1)*n+j].len=a[i][j];
        }
    fo(i,1,n) {
        f[i]=i;
        if (a[i][i]!=0) {
            puts("NOT MAGIC");
            return 0;
        }
        fo(j,1,n) if (a[i][j]!=a[j][i]) {
            puts("NOT MAGIC");
            return 0;
        }
    }
    sort(s+1,s+n*n+1,cmp);
    fo(i,1,n*n) {
        if (tot==n-1) break;
        int fx=getf(s[i].x),fy=getf(s[i].y);
        if (fx==fy) continue;
        f[fx]=fy;
        tot++;
        insert(s[i].x,s[i].y,s[i].len);
        insert(s[i].y,s[i].x,s[i].len);
    }
    dfs(1,0);
    fa[1][0][0]=1;
    fo(j,1,12)
        fo(i,1,n) {
            fa[i][j][0]=fa[fa[i][j-1][0]][j-1][0];
            fa[i][j][1]=max(fa[i][j-1][1],fa[fa[i][j-1][0]][j-1][1]);
        }
    fo(i,1,n) 
        fo(j,1,n) {
            if (j>=i) break;
            if (calc(i,j)!=a[i][j]) {
                puts("NOT MAGIC");
                return 0;
            }
        }
    puts("MAGIC");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章