传送门:QAQ
题意:第一天有n道菜,第二天有m道菜,然后有n行,每i行的第j个代表第一天的第i个菜与第二天的第m个菜的关系(>,<,=)。
让你这些菜的价值符合题目提出的要求,并且价值最小,让你输出是否存在,并且输出每个菜的价值
思路:如果没有=号,就是裸的拓扑排序,那么我们就要判断=带来的影响(两个相等的点之间存在大小关系,这可以用并查集,还有一个就是当前点的价值来自于所有相等点的价值的最大值)。
然后我们将输入离散化为n+m个点,将输入按大小关系建图,跑拓扑排序的操作即可。
附上比赛代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;
vector<int>gx[2200];
int father[2200];
char ch[1100][1100];
vector<int>mm[2200];
vector<int>vv;
int ax[2100];
int vis[2200];
int vis2[2200];
int ggg[2200];
int n, m;
int flag;
int tot;
int find(int x) {
if (x == father[x]) return x;
else return father[x] = find(father[x]);
}
void unio(int a, int b) {
int x = find(a);
int y = find(b);
if (x != y) {
father[x] = y;
}
}
int dfs(int x) {
vis[x] = 1;
tot++;
if (gx[x].size() == 0) {
int ans = 1;
if (mm[x].size() >= 1) {
for (int z = 0; z < mm[x].size(); z++) {
for (int i = 0; i < gx[mm[x][z]].size(); i++) {
if (find(mm[x][z]) == find(gx[mm[x][z]][i])) {
flag = 1;
break;
}
if (vis2[gx[mm[x][z]][i]] == 1) {
flag = 1;
return 0;
}
if (vis[gx[mm[x][z]][i]] == 1) {
ans = max(ans, ggg[gx[mm[x][z]][i]] + 1);
continue;
}
vis2[mm[x][z]] = 1;
ans = max(ans, dfs(gx[mm[x][z]][i]));
vis2[mm[x][z]] = 0;
if (flag)
return 0;
}
}
}
ggg[x] = max(ggg[x], ans);
return ans+1;
}
int ans = 0;
for (int i = 0; i < gx[x].size(); i++) {
if (find(x) == find(gx[x][i])) {
flag = 1;
break;
}
if (vis2[gx[x][i]] == 1) {
flag = 1;
return 0;
}
if (vis[gx[x][i]] == 1) {
ans = max(ans, ggg[gx[x][i]] + 1);
continue;
}
vis2[gx[x][i]] = 1;
ans = max(ans, dfs(gx[x][i]));
vis2[gx[x][i]] = 0;
if (flag)
return 0;
}
for (int z = 0; z < mm[x].size(); z++) {
for (int i = 0; i < gx[mm[x][z]].size(); i++) {
if (find(mm[x][z]) == find(gx[mm[x][z]][i])) {
flag = 1;
break;
}
if (vis2[gx[mm[x][z]][i]] == 1) {
flag = 1;
return 0;
}
if (vis[gx[mm[x][z]][i]] == 1) {
ans = max(ans, ggg[gx[mm[x][z]][i]] + 1);
continue;
}
vis2[mm[x][z]] = 1;
ans = max(ans, dfs(gx[mm[x][z]][i]));
vis2[mm[x][z]] = 0;
if (flag)
return 0;
}
}
for (int i = 0; i < mm[x].size(); i++) {
ggg[mm[x][i]] = ans;
}
ggg[x] = max(ggg[x], ans);
return ans + 1;
}
int main(void) {
tot = 0;
memset(vis, 0, sizeof(vis));
memset(ggg, 0, sizeof(ggg));
flag = 0;
scanf("%d%d", &n, &m);
for (int i = 0; i <= n + m; i++) {
father[i] = i;
}
for (int i = 0; i < n; i++) {
scanf("%s", ch[i]);
}
for (int i = 0; i < n; i++) {
for (int z = 0; z < m; z++) {
if (ch[i][z] == '<') {
gx[z + n + 1].push_back(i + 1);
ax[i + 1]++;
}
else if (ch[i][z] == '>') {
ax[n + z + 1]++;
gx[i + 1].push_back(z + n + 1);
}
else {
mm[i + 1].push_back(z + n + 1);
mm[z + n + 1].push_back(i + 1);
unio(z + n + 1, i + 1);
}
}
}
for (int i = 1; i <= n + m; i++) {
if (ax[i] == 0) vv.push_back(i);
}
for (int i = 0; i <vv.size(); i++) {
if (!vis[vv[i]]) {
memset(vis2, 0, sizeof(vis2));
vis2[vv[i]] = 1;
dfs(vv[i]);
if (flag == 1)
break;
}
}
if (flag == 1 || tot != n + m) {
printf("No\n");
}
else {
printf("Yes\n");
for (int i = 1; i <= n; i++) {
printf("%d ", ggg[i]);
}
printf("\n");
for (int i = n + 1; i <= n + m; i++) {
printf("%d ", ggg[i]);
}
printf("\n");
}
}