CF632F
Posted scanf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF632F相关的知识,希望对你有一定的参考价值。
题目大意:
给你一个 n阶方阵 An,判断它是否满足:
- aii=0;
- aij=aji;
- aij≤max{aik,ajk}。
其中n<=2500
题解:两个特判题目中给的比较清楚很简单的可以判定掉
考虑如何构造ai,j<=max(ai,k,ajk)
显然的我们索性让i,j之间连一条ai,j的边
然后跑一遍最大生成树
求出两点之间的最大值,看看是否与给定的ai,j矛盾即可
#include<bits/stdc++.h> #define N 5005 using namespace std; int fa[N],G[N][N],a[N][N],head[N],n,kk,cnt; struct Node{int x,y,d;}p[N*N]; struct Tree{int nxt,to,step;}e[N]; inline bool cmp(Node aa,Node bb){return aa.d<bb.d;} inline void link(int x,int y,int z){e[++kk].nxt=head[x];e[kk].to=y;e[kk].step=z;head[x]=kk;} inline int find(int x){if(fa[x]==x)return x;return fa[x]=find(fa[x]);} inline void make(int x,int y){fa[find(x)]=find(y);} void dfs(int u,int fa,int p,int mx){ for (int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if (v==fa) continue; G[p][v]=max(mx,e[i].step); dfs(v,u,p,G[p][v]); } } int main(){ scanf("%d",&n); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) scanf("%d",&a[i][j]); for (int i=1;i<=n;i++) if (a[i][i]) return puts("NOT MAGIC"),0; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (a[i][j]!=a[j][i]) return puts("NOT MAGIC"),0; for (int i=1;i<=n;i++) for (int j=i+1;j<=n;j++) p[++cnt].x=i,p[cnt].y=j,p[cnt].d=a[i][j]; sort(p+1,p+cnt+1,cmp); for (int i=1;i<=n;i++) fa[i]=i; for (int i=1;i<=cnt;i++){ if (find(p[i].x)!=find(p[i].y)){ link(p[i].x,p[i].y,p[i].d); link(p[i].y,p[i].x,p[i].d); make(p[i].x,p[i].y); } else continue; } for (int i=1;i<=n;i++) dfs(i,-1,i,0); for (int i=1;i<=n;i++) for (int j=i+1;j<=n;j++) if (G[i][j]!=a[i][j]) return puts("NOT MAGIC"),0; puts("MAGIC"); return 0; }
以上是关于CF632F的主要内容,如果未能解决你的问题,请参考以下文章