您的位置:首页 > 其它

codeforces 632F

2016-04-12 22:28 375 查看

题目大意

给定一个矩阵AA,大小是n∗n,n≤2500n*n,n\leq2500,判断这个矩阵是否是MagicMagic的。

一个矩阵是MagicMagic的,必须满足。

1.ai,i=01.a_{i,i}=0

2.ai,j=aj,i2.a_{i,j}=a_{j,i}

3.3.对于∀i,j,k\forall i,j,k满足ai,j≤max(ai,k,aj,k)a_{i,j}\leq max(a_{i,k},a_{j,k})

解题思路

我们不妨把ai,ja_{i,j}看做在一个图中i→ji\rightarrow j有一条长度为ai,ja_{i,j}的双向边。这样就可以满足条件1和条件2。我们可以设fi,jf_{i,j}为ii到jj的任意路径的最长边的最小值,可得ai,j≥fi,ja_{i,j}\geq f_{i,j}.

假设一个矩阵满足条件,则ai,j≤max(ai,k1,ak1,j)a_{i,j}\leq max(a_{i,k_1},a_{k_1,j}),ai,k1≤max(ai,k2,ak2,k1)a_{i,k_1}\leq max(a_{i,k_2},a_{k_2,k_1})……,把式子代入可以发现,ai,j≤max(ai,k1,ak1,k2,ak2,k3...,akm,j)=fi,ja_{i,j}\leq max(a_{i,k_1},a_{k_1,k_2},a_{k_2,k_3}...,a_{k_m,j})=f_{i,j}.

∴ai,j=fi,j\therefore a_{i,j}=f_{i,j}.

判断矩阵是否合法,就是判断图上的ii到jj的任意路径的最长边的最小值是否等于ai,ja_{i,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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: