专栏文章
题解:P13956 [ICPC 2023 Nanjing R] 等价重写
P13956题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minnhvwy
- 此快照首次捕获于
- 2025/12/02 05:17 3 个月前
- 此快照最后确认于
- 2025/12/02 05:17 3 个月前
思路
昨天写了一下,为了准备区域赛,其实整套题做的很烂,写一下题解复盘。
这道题其实就是基本的拓扑排序,不难发现一个点如果被几个数字先后染色,只要保证最后一个染色数字不变就行,因此就说明最后的这个数字是前面数字的上级。同理,这样对每个位置都找到一个这样的顺序,就可以构成一个类似食物链的结构,就是拓扑图。因此只要拓扑排序一下,就可以找到解。但是要和原来的不同,因此就要用优先队列,第一关键字的等级,第二关键字的编号。编号我们逆序即可,最后判断一下是不是原有的顺序就行。
代码
CPP#include<iostream>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;
const int N = 100005;
typedef pair<int, int>PII;
vector<int>paint[N];
vector<int>to[N];
vector<int>ans;
int cnt[N] = {}, f[N] = {};
int main(void) {
int t;
cin >> t;
while (t--) {
ans.clear();
memset(cnt, 0, sizeof(cnt));
priority_queue<PII, vector<PII>, greater<PII>>Q;
int n, m, sum = 0;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
int num;
cin >> num;
for (int j = 1; j <= num; j++) {
int k;
cin >> k;
paint[k].push_back(i);
f[k] = i;
}
}
for (int i = 1; i <= m; i++) {
for (int j = 0; j < int(paint[i].size()) - 1; j++) {
int u = paint[i][j];
to[u].push_back(f[i]);
cnt[f[i]]++;
}
}
for (int i = 1; i <= n; i++) {
if (!cnt[i])Q.push(make_pair(0, -i));
}
while (!Q.empty()) {
int dp = Q.top().first, u = Q.top().second * (-1);
Q.pop();
ans.push_back(u);
for (int i = 0; i < to[u].size(); i++) {
int k = to[u][i];
cnt[k]--;
if (!cnt[k])Q.push(make_pair(dp + 1, k * (-1)));
}
}
bool ok = false;
for (int i = 0; i < ans.size(); i++) {
if (ans[i] != i + 1) {
ok = true;
break;
}
}
if (ok) {
cout << "Yes" << endl;
for (int i = 0; i < n; i++) cout << ans[i] << ' ';
cout << endl;
}
else {
cout << "No" << endl;
}
for (int i = 1; i <= m; i++) paint[i].clear();
for (int i = 1; i <= n; i++)to[i].clear();
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...