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; }
相关文章推荐
- 为什么要写博客?
- OC阅读笔记十九:禁用retainCount
- 商翼ERC企业管理软件是如何管理生产企业销售与生产!
- Failed to load native-hadoop本地库不一致的解决办法
- 为什么要写博客?
- FFMPEG SDK 开发介绍
- Android样式的开发:selector篇
- LeetCode 97. Interleaving String
- 网络:GET 登录和转码
- oracle 执行计划里的cost(%CPU)与consistent gets
- 关于狄利克雷分布的理解
- 无限级下拉菜单---jQuery+css 实现的超酷无限级下拉菜单
- C/C++中二级指针的理解
- 求最大公约数
- 不同shell文件中的函数调用
- 错误代码: 1017 Can't find file: '.\bus\t_driver_info@ff1b.frm' (errno: 22 - Invalid argument)
- 禅道数据库修改方法(实践篇)
- javascript事件详解笔记
- 测试用例优先级与三轮测试的结合
- 内存对齐与补齐 字节对齐与结构体大小