没什么特别大的感慨
并查集的使用与拓扑的升级版本
链接:https://codeforces.com/problemset/problem/1131/D
代码:
//Problem:
//Date:
//Skill:
//Bug:
/////////////////////////////////////////Definations/////////////////////////////////////////////////
//循环控制
#define CLR(a) memset((a),0,sizeof(a))
#define F(i,a,b) for(int i=a;i<=int(b);++i)
#define F2(i,a,b) for(int i=a;i>=int(b);--i)
#define RE(i,n) for(int i=0;i<int(n);i++)
#define RE2(i,n) for(int i=1;i<=int(n);i++)
//输入输出
//#define INC(c) do{scanf("%c",&c);}while(isspace(c))
//#define ON cout<<endl
#define PII pair<int,int>
using namespace std;
const int inf = 0x3f3f3f3f;
const long long llinf = 0x3f3f3f3f3f3f3f3f;
////////////////////////////////////////Options//////////////////////////////////////////////////////
typedef long long ll;
#define stdcpph
#define CPP_IO
#ifdef stdcpph
#include<bits/stdc++.h>
#else
#include<ctype.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<algorithm>
#include<functional>
#ifdef CPP_IO
#include<iostream>
#include<iomanip>
#include<string>
#else
#include<stdio.h>
#endif
#endif
////////////////////////////////////////Basic Functions//////////////////////////////////////////////
template<typename INint>
inline void IN(INint &x)
{
x = 0; int f = 1; char c; cin.get(c);
while (c<'0' || c>'9') { if (c == '-')f = -1; cin.get(c); }
while (c >= '0'&&c <= '9') { x = x * 10 + c - '0'; cin.get(c); }
x *= f;
}
template<typename INint>
inline void OUT(INint x)
{
if (x > 9)OUT(x / 10);
cout.put(x % 10 + '0');
}
////////////////////////////////////////Added Functions//////////////////////////////////////////////
const int maxn = int(1e3 + 5);
int n, m;
vector<int>fa(1,-1);
int ff(int x) {
return fa[x] == x ? x : fa[x] = ff(fa[x]);
}
void mer(int x, int y)
{
int fx = ff(x), fy = ff(y); fa[fx] = fy;
}
string ss[maxn];
int in[maxn * 2], res[maxn * 2];
int ma[maxn*2][maxn*2];
int ans[maxn * 2], rk[maxn * 2];
int topu(int n, int indegree[], int result[])//必须之前统计入度
{
queue<int> Q; int cnt(0);
for (int i = 1; i <= n; i++)if(fa[i]==i)
if (indegree[i] == 0)
{
Q.push(i);//将 没有依赖顶点的节点入队
rk[i] = 1;
//result[cnt++] = i;
}
while (!Q.empty()) //
{
int u = Q.front(); Q.pop();//删除队顶元素
result[++cnt] = u;//将上边选出的没有依赖顶点的节点加入到排序结果中
for (int i = 1; i <= n; i++)if (fa[i] == i)
{
if (ma[u][i])
{
rk[i] = max(rk[i], rk[u] + 1);
indegree[i] --;//删去以u为顶点的边
if (indegree[i] == 0) //如果节点i的所有依赖顶点连接边都已经删去
Q.push(i); //即变为无依赖顶点的节点 将其入队
}
}
}
return cnt;//返回成功确定顺序的节点数
}
////////////////////////////////////////////Code/////////////////////////////////////////////////////
int main()
{
//freopen("C:\\Users\\VULCAN\\Desktop\\data.in", "r", stdin);
int T(1), times(0);
#ifdef CPP_IO// CPP_IO
std::ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
//cin >> T;
#else
//IN(T);
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////
while (++times, T--)
{
cin >> n >> m;
RE2(i, n + m)fa.push_back(i);
RE2(i, n)cin >> ss[i];
RE2(i, n)
{
RE2(j, m)
{
char c; c = ss[i][j - 1];
if (c == '=') /*E[i].push_back(j + n), E[j + n].push_back(i),*/
mer(i, j + n);
}
}
RE2(i, n + m)fa[i] = ff(i);
RE2(i, n)
{
RE2(j, m)
{
char c; c = ss[i][j - 1];
//if (fa[i] == fa[j + n])continue;
if (c == '<') ma[fa[i]][fa[j+n]] = 1;
else if(c=='>') ma[fa[j+n]][fa[i]] = 1;
}
}
RE2(i, n + m)RE2(j, n + m)if (ma[i][j])++in[j];
bool flag = 1;
RE2(i, n + m)if (ma[i][i])flag = 0;
int amo(0);
RE2(i, n + m)amo += fa[i] == i;
int cnt=topu(n + m, in, res);
if ((cnt != amo)|| !flag)
{
cout << "No" << endl; continue;
}
else cout << "Yes" << endl;
//RE2(i, n + m)rk[res[i]] = i;
RE2(i, n + m)
ans[i] = rk[fa[i]];
RE2(i, n)
{
if (i - 1)cout << ' ';
cout << ans[i];
}
cout << endl;
RE2(i, m)
{
if (i - 1)cout << ' ';
cout << ans[i + n];
}
//cout << ans << endl;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
return 0;
}