有两个正整数序列 (a,b),长度分别为 (n,m)。给出所有 (a_i) 和 (b_j) ((1le ile n,1le jle m)) 的大小关系(大于,小于或者等于),请构造出符合条件的 (a) 和 (b)。如果无解,输出 NO
。如果有多个解,输出 (a,b) 中最大元素最小的方案。
Solution
并查集将所有等于的数合并起来,然后建图拓扑排序,最后 check
一下拓扑排序的结果以检查是否有环
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2005;
int n,m,g[N][N],fa[N],a[N],b[N];
char c[N][N];
int find(int p) {
return fa[p]==p ? p : fa[p]=find(fa[p]);
}
void merge(int p,int q) {
p=find(p); q=find(q);
if(p!=q) fa[p]=q;
}
void dfs(int p) {
b[p]=1;
for(int i=1;i<=n+m;i++) {
if(g[p][i]) {
if(b[i]) {
cout<<"No";
exit(0);
}
if(a[i]==0) dfs(i);
a[p]=max(a[p],a[i]);
}
}
b[p]=0;
++a[p];
}
signed main() {
cin>>n>>m;
for(int i=1;i<=n+m;i++) fa[i]=i;
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
cin>>c[i][j];
if(c[i][j]=='=') {
merge(i,n+j);
}
}
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
if(c[i][j]=='<') {
g[find(j+n)][find(i)]=1;
}
if(c[i][j]=='>') {
g[find(i)][find(j+n)]=1;
}
}
}
for(int i=1;i<=n+m;i++) if(a[i]==0) dfs(i);
cout<<"Yes"<<endl;
for(int i=1;i<=n;i++) cout<<a[find(i)]<<" ";
cout<<endl;
for(int i=1;i<=m;i++) cout<<a[find(i+n)]<<" ";
cout<<endl;
}