题意:第一天有n道菜,第二天有m道菜,给出第一天每道菜跟第二天每道菜比较的结果,存在“=”,“<”,“>”三种结果,根据该结果对所有菜进行一个等级的划分,并要求菜的最大等级要尽量小。
题解:乍一看蛮像拓扑排序的,其实就是拓扑排序,只不过存在“=”这种比较结果,不过也很好处理,根据并查集将=的划分在同一个生成树里面,即利用tarzan缩点,最后跑一遍拓扑排序就好了。
hint:不知道为啥这个拓扑排序我用queue就WA用stack就AC,很奇怪。
附上ACcode:
#include <bits/stdc++.h>
#define FOPI freopen("INPUT.TXT", "r", stdin)
#define DOPI freopen("OUTPUT.TXT", "w", stdout)
#define FOR(i, x, y) for(int i = x; i <= y; i ++)
#define ROF(i, x, y) for(int i = x; i >= y; i --)
using namespace std;
typedef long long int ll;
const int ind=0x3f3f3f3f,N=1e3+10;
int f[N*N];
char ch[N][N];
int n,m;
int getf(int x){return f[x]==x?x:f[x]=getf(f[x]);}
vector<int> v[N*N];
int cnt[N*N];
int book[N*N];
int ans[N*N];
void dfs()
{
stack<int> q;
for(int i=1;i<=n+m;i++)book[i]=0;
for(int i=1;i<=n+m;i++){
int fi=getf(i);
if(!cnt[fi]){
q.push(fi);
book[fi]=1;
ans[fi]=1;
}
}
while(!q.empty()){
int ti=q.top();
q.pop();
for(int i=0;i<v[ti].size();i++){
if(--cnt[v[ti][i]]==0&&book[v[ti][i]]==0){
ans[v[ti][i]]=ans[ti]+1; book[v[ti][i]]=1; q.push(v[ti][i]);}
}
// cout << "here" << endl;
}
}
void merge_it(int x,int y)
{
int xx=getf(x);
int yy=getf(y);
if(xx!=yy)f[xx]=yy;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n+m;i++)f[i]=i;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>ch[i][j];
if(ch[i][j]=='='){
merge_it(i,n+j);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(ch[i][j]=='<'){
int fi=getf(i);
int fj=getf(j+n);
v[fi].push_back(fj);
cnt[fj]++;
}
else if(ch[i][j]=='>'){
int fi=getf(i);
int fj=getf(j+n);
v[fj].push_back(fi);
cnt[fi]++;
}
}
}
dfs();
for(int i=1;i<=n+m;i++){
if(book[getf(i)]==0){
cout << "No" << endl;return 0;
}
}
cout << "Yes" << endl;
for(int i=1;i<=n;i++){
if(i==1)cout << ans[getf(i)];
else cout << ' ' << ans[getf(i)];
}cout << endl;
for(int i=n+1;i<=n+m;i++){
if(i==n+1)cout << ans[getf(i)];
else cout << ' ' << ans[getf(i)];
}cout << endl;
return 0;
}